EasySearch and EPiServer: Scoped search and Globalization issues
<p>In one of our projects we included EasySearch into our globalized enterprise solutions which introduced us to a few issues. The two main ones were: scoped search and search with fallback languages.</p>
Fallback languages:
We quickly discovered that EasySearch doesn't include any fallback languages in the search. To make this work we needed to make one main query for current language and one for the fallback language (if the the language had a fallback language configured). Code example for this:
Query query = queryInterface.GetQuery(str, CurrentPage.LanguageBranch, IndexFieldNames.PrimaryContentFieldName, true, null);
//Check if language might be a fallback language
string fallbackLang = GetLanuages(EPiServer.Globalization.ContentLanguage.PreferredCulture.IetfLanguageTag);
Query fallbackQuery = null;
if (!string.IsNullOrEmpty(fallbackLang))
{
fallbackQuery = queryInterface.GetQuery(str, fallbackLang, IndexFieldNames.PrimaryContentFieldName, true, null);
}
var combinedQuery = new BooleanQuery();
combinedQuery.Add(query, BooleanClause.Occur.SHOULD);
if(fallbackQuery !=null)
combinedQuery.Add(fallbackQuery, BooleanClause.Occur.SHOULD);
MasterQuery.Add(combinedQuery, BooleanClause.Occur.MUST);
We now have a master query which checks both current language and a fallback language.
Scoped search:
We also had a issue when it came to scoped search (searching within one specific branch in the solution). Luckily for us EasySearch already indexes the page path (rootid_startpageid_pageid_etc) and we found out that we could use this to scope our search like this (here we wanted to only include pages for this startpage in our enterprise solution):
string path = string.Format("{0}_*", ComputePagePath(GetPage(PageReference.StartPage)));
WildcardQuery pathQuery = new WildcardQuery(new Term(IndexFieldNames.PagePath, path));
MasterQuery.Add(pathQuery, BooleanClause.Occur.MUST);
And where ComputePagePath function looked like this:
private static string ComputePagePath(PageData page)
{
string pagePath = page.PageLink.ID.ToString();
PageData parent = GetParent(page);
while (parent != null)
{
pagePath = parent.PageLink.ID + "_" + pagePath;
parent = GetParent(parent);
}
return pagePath;
}
private static PageData GetParent(PageData page)
{
if (page.ParentLink == null)
{
return null;
}
if (page.ParentLink.ID == 0)
{
return null;
}
return DataFactory.Instance.GetPage(page.ParentLink);
}
One big thing to notice is that when using wildcard search you need to specify the max number of clauses in your search or you might get an error saying that: Exception Details: Lucene.Net.Search.BooleanQuery+TooManyClauses.
To do this you just need to add:
BooleanQuery.SetMaxClauseCount(int.MaxValue);
just after you get the QueryInterface
And that's that: you now have a scoped search that works for fallback languages as well :)