I am trying to implement a simple search functionality in Piranha CMS. This uses a separate controller and an input string "q" which is the result of a form GET-call. The string is splitted at each space into a list of strings called Keywords.
I have achieved a simple search which successfully retrieves pages and posts based on title and post's excerpt and body. However since the pages consists of arbitrary regions one cannot simply query those directly. I have tried getting the value of the Region's body in multiple ways but I end up getting a NotSupportedException with the following message:
The specified type member 'Body' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
I figured out that I am would get this if Body is not mapped to a column in the database. However, the information must be stored somewhere and since I would like to use the supplied DataContext without accessing the database directly I am wondering how to get the content prior enumeration.
I can see that the content is loaded at enumeration but I want to avoid loading all pages and instead doing the filtering in the query.
Can someone please guide me in the correct direction. I have supplied a snippet from the Controller which successfully queries posts and pages by title.
using (Piranha.DataContext db = new Piranha.DataContext())
{
var pages = db.Pages.Include("Regions").Where(p => Keywords.Any(keyword => p.Title.Contains(keyword)));
var posts = db.Posts.Where(p => Keywords.Any(keyword => p.Title.Contains(keyword) || p.Excerpt.Contains(keyword) || p.Body.Contains(keyword)));
if (pages != null)
{
foreach (var page in pages)
{
Model.Results.Add(new SearchResultsModel.SearchResult()
{
Title = page.Title,
Id = page.Id
});
}
}
if (posts != null)
{
foreach (var post in posts)
{
Model.Results.Add(new SearchResultsModel.SearchResult()
{
Title = post.Title,
Id = post.Id
});
}
}
}
Thanks in advance.
Yes, database structure for pages is rather complex, and in order to support all kinds of objects as region body the data is serialized as JSON. The Body
property is in fact an ignored property that contains the deserialized JSON data for the region. Unfortunately the "real" body of the region (which you could run a LINQ query on) is hidden to avoid confusion. You can find it here:
https://github.com/PiranhaCMS/Piranha/blob/2.2.4/Piranha/Entities/Region.cs#L80
However, your use case is completely valid, and if you're compiling against source code and have a fork on GitHub, feel free to change the access modified to public and send me a pull request. I'll include it in the next release!
If you're using NuGet packages you'll have to to some real SQL and wait for the patch to be released.
I've added a feature request issue on the GitHub repo here:
https://github.com/PiranhaCMS/Piranha/issues/365
Regards
Håkan