我遇到了一个有趣的Linq to Sitecore问题。 我有一个人员目录和一个位置目录,这些目录都存储在 Sitecore 中。我正在尝试编写一个搜索函数,使我能够搜索附近的人。除此之外,人们可以与多个位置相关联。
到目前为止,方法是找到附近的位置,获取他们的ID,然后找到与这些位置相关的所有人员。
这大致看起来像:
var locations = GetNearbyLocations(lat, long, radius) // returns a list of short ID's
var searchPredicate = PredicateBuilder.True<SearchResultItem>();
var locationsPredicate = PredicateBuilder.False<SearchResultItem>();
foreach (var location in locations)
{
locationPredicate = locationPredicate.Or(x => x["location"] == location);
}
searchPredicate = searchPredicate.And(locationPredicate);
searchPredicate = searchPredicate.And(sri => sri.TemplateId == personTemplateId);
using (var context = index.CreateSearchContext())
{
var peopleReults = context.GetQueryable<SearchResultItem>.Where(locationPredicate).GetResults();
}
如果GetNearbyLocations
返回一组相对较小的位置,则上述方法效果很好。一旦我们超过 150 个左右,对 GetQuerable
的调用将导致堆栈溢出。
您可能可以使用位置数组并执行包含。
locationPredicate.And(x=>locations.Contains(x["location"]));
如果您从该病中得到一个很大的错误,请发布一些您可以使用的 lambda 表达式。
Lucene 一次只能处理 1024 个子句。
有一个名为 ContentSearch.LuceneQueryClauseCount 的 Sitecore 设置应该强制 Lucene 接受您在设置中定义的任何数量的子句,但它似乎不起作用。 更改此设置的值似乎不会在搜索操作期间执行任何操作。 有一种方法可以强制读取此设置并强制 Lucene 一次接受超过 1024 个 OR 子句。 增加此设置的值,在执行搜索之前,运行以下代码行:
BooleanQuery.MaxClauseCount = int.Parse(Sitecore.Configuration.Settings.GetSetting("ContentSearch.LuceneQueryClauseCount"));
这允许您提交包含超过 1024 个子句的查询,但是,在某些时候,Lucene 仍将抛出 StackOverflowException。要绕过 Lucene 限制,您必须以 1024 的增量分解 OR 子句的数量,并且每次都使用 OR 子句的子集执行多次搜索。