Geta

Menu US

Searching multiple Find indexes

Recently I helped out investigating an issue where the search result from Find contained non-published and deleted pages. The site in question had a search page that fetched results from two separate Find indexes.

Communicating with the REST API - the basics

All communication with Find's REST API goes through an instance of the IClient interface. To obtain such an instance you can use the Client.CreateFromConfig() method that will create it based on settings in app.config/web.config.
Note that if you are using Find with any other EPiServer Products, like CMS or Commerce, you should always use the SearchClient.Instance singleton.
This is important since the client holds a number of default conventions related to how different types should be serialized, how they define IDs and more.

When you have multiple indexes

Lets say you want to show results from two separate Find indexes. For the current site you should, as described above, always use the SearchClient.Instance singelton. For the second index, we need to create the IClient ourselves.

var currentSiteSearchResult = SearchClient.Instance.Search<PageData>()
.For(query).GetContentResult();
//get serviceUrl and indexName values from appSettings or similar
var remoteSearchClient = new Client(serviceUrl, indexName);
var remoteSiteSearchResult = remoteSearchClient.UnifiedSearchFor(query).GetResult();

As previously mentioned, there was an issue with deleted and non-published pages being part of the remote search result. Basically the remoteSearchClient needs to be configured with the same conventions as you "get for free" through the SearchClient.Instance singelton. You can do this by adding a PublicSearchFilter to the UnifiedSearchRegistry:

remoteSearchClient.Conventions.UnifiedSearchRegistry.Add<PageData>()
.PublicSearchFilter((IClient c, ISearchContext ctx) =>
c.BuildFilter<IContentData>()
.FilterForVisitor<IContentData>(this.GetLanguage(ctx))
.ExcludeContainerPages<IContentData>()
.ExcludeContentFolders<IContentData>()
.FilterOnCurrentSite<IContentData>());
private string GetLanguage(ISearchContext context)
{
if (context.Payload.ContainsKey("Culture") && context.Payload["Culture"].IsNotNull())
{
return ((CultureInfo)context.Payload["Culture"]).Name;
}
if (context.Language == null || context.Language == Language.None)
{
return Languages.AllLanguagesSuffix;
}
return context.Language.FieldSuffix;
}
comments powered by Disqus

IClient vs SearchClient.Instance

If you're using the CMS integration or any other integration for other EPiServer products always use the singleton SearchClient.Instance.