So here is the summary:
Sitecore - SOLR index query
I have items that I am trying to retrieve using a set of sites that can vary.
I have a query:
query = query.Where(x => x.Language == this.ItemLanguage)
.Where(x => x.Templates.Contains(new Guid("94c1f3e5ac174a319cc5bbb942fe80c6")));
this will return all of the items correctly.
What I need is to add a dynamic list call for this query.
Something like:
.Where(x => x.Site.Any(y => siteNames.Contains(y)));
I have tried adding this line of code and I get an error:
System.ArgumentException: 'Argument must be array'
(some details)
Items returned (x) have a field "Site" of List<string>
siteNames is a List<String>
of variable site names
The following code works in other places:
.Where(x => x.Site.Contains("somesite"));
Is there a way to manage a dynamic list or will I need to manually generate this expression based on the number of items in the siteNames list?
.Where(x => x.Site.Contains("dynamic") || x.Site.Contains("dynamic")
|| x.Site.Contains("dynamic") || x.Site.Contains("dynamic")
|| and so on);
Here is the full code example:
using (var context = Sitecore.ContentSearch.ContentSearchManager.GetIndex(AccelConstants.SEARCH_INDEX).CreateSearchContext())
{
IQueryable<SearchResultModel> query = context.GetQueryable<LMSSearchResultModel>();
SearchResults<SearchResultModel> results = null;
List<string> siteNames = new List<string>();
siteNames = this.SiteNames;
// Define the base search
query = query.Where(x => x.Language == this.ItemLanguage)
.Where(x => x.Templates.Contains(new Guid("94c1f3e5ac174a319cc5bbb942fe80c6")))
.Where(x => x.Site.Any(p => siteNames.Contains(p)));
// Execute the query
results = query.GetResults();
}
the site field is a solr field of Site_SM which outputs like this: The reason the name "Site" is used is that Sites is also a field. This is not code that I have control over so I am working with what I have.
"site_sm":["login", "admin", "service", "covid19", "scheduler", "system", "publisher"],
The search results model simply converts computed solr fields to c#
public class SearchResultModel : SearchResultItem
{
[IndexField("_templates")]
public List<Guid> Templates { get; set; }
[IndexField("site_sm")]
public List<string> Site { get; set; }
}
OK, so here is a rather hacked way of making my search work.
using (var context = Sitecore.ContentSearch.ContentSearchManager.GetIndex(AccelConstants.SEARCH_INDEX).CreateSearchContext())
{
IQueryable<SearchResultModel> query = context.GetQueryable<LMSSearchResultModel>();
SearchResults<SearchResultModel> results = null;
List<string> siteNames = new List<string>();
siteNames = this.SiteNames;
// Define the base search
// remove site filtering from query
query = query.Where(x => x.Language == this.ItemLanguage)
.Where(x => x.Templates.Contains(new Guid("94c1f3e5ac174a319cc5bbb942fe80c6")));
// Execute the query
results = query.GetResults();
// Get the results
foreach (var hit in results.Hits)
{
//move site filter code to here
if (hit.Document != null && hit.Document.Site.Any(p => siteNames.Contains(p)))
{
// Add the model to the results.
}
else
{
}
}
}
By moving the site filter code to after the query, the Site List<string>
is instantiated and has value at the time of the call. Which seems to have been my issue.
This then allows me to filter by the sites in the siteNames List<string>
and get my final result set.
I don't know if this is the best way of making this section of code work but it does work.