November Happy Hour will be moved to Thursday December 5th.
AI OnAI Off
November Happy Hour will be moved to Thursday December 5th.
Hi Marshall,
So, I assume you are talking about the built-in Episerver search? It is annoying that it doesn't index everything, but, I think that is on purpose becasue they want people to use Find. Anyway, here is what you do to index custom fields.
First, create an init module:
[InitializableModule] [ModuleDependency(typeof(EPiServer.Web.InitializationModule))] public class SearchInitialization : IInitializableModule { public void Initialize(InitializationEngine context) { IndexingService.DocumentAdding += CustomizeIndexing; } public void Uninitialize(InitializationEngine context) { IndexingService.DocumentAdding -= CustomizeIndexing; } void CustomizeIndexing(object sender, EventArgs e) { var addUpdateEventArgs = e as AddUpdateEventArgs; if(addUpdateEventArgs == null) { return; //Document is not being added/updated } var document = addUpdateEventArgs.Document; var page = document.GetContent<IContent>() as PageData; if(page != null && page is SitePageData) { var examplePage = page as SitePageData; if(examplePage.YourCustomField != null) { document.Add(new Field("CUSTOM_FIELD", examplePage.YourCustomField, Field.Store.NO, Field.Index.ANALYZED)); } } } }
Here is the extension method GetContent that the variable page is using when getting set:
public static class DocumentHelper { public static T GetContent<T>(this Document document) where T : IContent { const string fieldName = "EPISERVER_SEARCH_ID"; var fieldValue = document.Get(fieldName); if(string.IsNullOrWhiteSpace(fieldValue)) { throw new NotSupportedException( string.Format("Specified document did not have a '{0}' field value", fieldName)); } var fieldValueFragments = fieldValue.Split('|'); Guid contentGuid; if(!Guid.TryParse(fieldValueFragments[0], out contentGuid)) { throw new NotSupportedException( "Expected first part of ID field to be valid GUID"); } return ServiceLocator.Current.GetInstance<IContentLoader>().Get<T>(contentGuid); } }
Here is an example of a search query using the cutom field:
public void Search(string q) { var culture = ContentLanguage.PreferredCulture.Name; SearchResult = new List<IndexResponseItem>(); var query = new GroupQuery(LuceneOperator.AND); // Only search for pages query.QueryExpressions.Add(new ContentQuery<PageData>()); // Search for keywords in any of te fields specified below (OR condition) var keywordsQuery = new GroupQuery(LuceneOperator.OR); // Search in default fields keywordsQuery.QueryExpressions.Add(new FieldQuery(q)); // Search in the custom fields keywordsQuery.QueryExpressions.Add(new CustomFieldQuery(q, "CUSTOM_FIELD")); query.QueryExpressions.Add(keywordsQuery); // The access control list query will remove any pages the user doesn't have read access to var accessQuery = new AccessControlListQuery(); accessQuery.AddAclForUser(PrincipalInfo.Current, HttpContext.Current); query.QueryExpressions.Add(keywordsQuery); var fieldQueryResult = SearchHandler.Instance.GetSearchResults(query, 1, 40) .IndexResponseItems //.Where(x => // (x.Culture.Equals(culture) || string.IsNullOrEmpty(x.Culture)) // ) .ToList(); SearchResult.AddRange(fieldQueryResult); }
Lastly, when you update the field in your scheduled job, update the index:
var contentSearchHandler = ServiceLocator.Current.GetInstance<ContentSearchHandler>(); contentSearchHandler.UpdateItem(currentPage as IContent);
I hope this helps!
- John
Has anybody had any experience of the Episerver Search not indexing all the text fields in a page? I have a text field in my SitePageData which stubbonly refuses to show up in any searches. I have tried changing it to a XHTMLString to see if that makes any difference, but it does not. The field is updated from a scheduled task which collects all the text data from any blocks within the page. I know that the field is getting updated as the function that populates the fields can also read them out again to a log, with a different parameter.
The site is supposed to go live on 30th Dec so i am a bit worried
Thanks, in advance,
Marshall