我开始使用 RavenDB 几天以来,我已经陷入了困境,我认为应该很容易执行。
我想做的是搜索以获取属性Title
中包含用户键入的所有单词的产品列表。
一个例子:
product/1 -> title: "my awesome product"
product/2 -> title: "super product asd"
如果我搜索“prod per”,我希望只出现第二个产品作为结果。
在我的脑海里,我会做这样的事情
public IList<Product> GetBySearchTerms(string searchTerms, int pageIndex, int pageSize, out int totalItems)
{
pageIndex--;
if (pageIndex < 0)
pageIndex = 0;
IList<Product> result = new List<Product>();
var query = var query = session.Query<Product>().Statistics(out stats);
var termsList = searchTerms.Split(' ', StringSplitOptions.RemoveEmptyEntries);
foreach (var term in termsList)
query = query.Where(x => x.Title.Contains(term));
if (pageSize > 0)
result = query.Skip(pageIndex * pageSize).Take(pageSize).ToList();
else
result = query.ToList();
totalItems = stats.TotalResults;
return result;
}
经过一番挖掘,我发现第一个问题出在Contains
方法上。由于 RavenDB 中的搜索行为,它没有被实现/支持。
我应该改用该Search
方法,但我还读到*term*
由于性能问题,不应使用 using。
所以我最终在 RavenDB 中创建了一个像这样的索引
Name: ProductSearchByName
Map: from doc in docs.Products select new { Title = doc.Title }
和代码
public IList<Product> GetBySearchTerms(string searchTerms, int pageIndex, int pageSize, out int totalItems)
{
pageIndex--;
if (pageIndex < 0)
pageIndex = 0;
IList<Product> result = new List<Product>();
RavenQueryStatistics stats;
var query = session.Query<Product>("ProductSearchByName").Statistics(out stats);
query = searchTerms
.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)
.Aggregate(query, (q, term) => q.Search(x => x.Title, "*" + term + "*", options: SearchOptions.And, escapeQueryOptions: EscapeQueryOptions.AllowAllWildcards));
if (pageSize > 0)
result = query.Skip(pageIndex * pageSize).Take(pageSize).ToList();
else
result = query.ToList();
totalItems = stats.TotalResults;
return result;
}
此搜索可以满足我的需要,但我担心有关使用通配符的所有警告。
有没有办法在Contains
不使用的情况下获得结果*term*
?
这个问题的正确方法/解决方案应该是什么?