【发布时间】:2013-06-27 09:47:54
【问题描述】:
我从几天开始就开始使用 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*。
所以我最终在 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;
}
此搜索可以满足我的需要,但我担心有关使用通配符的所有警告。
有没有办法在不使用*term* 的情况下获得Contains 结果?
这个问题的正确方法/解决方案应该是什么?
【问题讨论】: