【发布时间】:2017-10-16 10:03:32
【问题描述】:
我有一个产品数据库(用于足球),其中包含大约 5k 种产品。用于产品搜索的 Lucene 索引当前包含名称、类别、颜色和编号(ArtNo 和 EAN)。
问题的相关表格示例:
| 姓名 | 颜色 | ------------------------------------------ |耐克训练足球 |红黑| |耐克比赛足球 |黑白| ------------------------------------------对于索引,我创建了一个自定义分析器,因此我可以扩展一个具有其他行为的 StandardAnalyzer。流的创建现在看起来像这样:
TokenStream result = new StandardTokenizer(Util.Version.LUCENE_29, reader );
result = new StandardFilter(result);
result = new LowerCaseFilter(result);
result = new StopFilter(true, result, stoptable );
return result;
分析器同时用于索引器和搜索器。
这是当前的搜索逻辑:
BooleanQuery booleanQuery = new BooleanQuery(true);
string[] terms = query.Split(' ');
foreach (string s in terms)
{
BooleanQuery subQuery = new BooleanQuery(true);
var nameQuery = new FuzzyQuery(new Term("Name", s), 0.9f);
nameQuery.SetBoost(6);
subQuery.Add(nameQuery, BooleanClause.Occur.SHOULD);
var colorQuery = new TermQuery(new Term("Color", s));
subQuery.Add(colorQuery, BooleanClause.Occur.SHOULD);
var categoryQuery = new FuzzyQuery(new Term("Category", s), 0.9f);
categoryQuery.SetBoost(2);
subQuery.Add(categoryQuery, BooleanClause.Occur.SHOULD);
var numbersQuery = new TermQuery(new Term("Numbers", s));
numbersQuery.SetBoost(10);
subQuery.Add(numbersQuery, BooleanClause.Occur.SHOULD);
booleanQuery.Add(subQuery, BooleanClause.Occur.MUST);
}
它已经以某种方式工作了。
问题:
许多产品的名称或类别都包含用户不会搜索的字词。 在示例中,我使用了“Nike Match football”。 (注意:我只翻译了它以用于 SO,因为数据库中的大多数术语都是德语)
如果我搜索“Nike football red”,我会得到结果。但如果搜索“Nike ball red”我不明白,尽管这是用户搜索它的方式。 Afaik Lucene 无法搜索子字符串(通配符除外),因为它只比较标记 - 我确实需要这样的东西。
我已将Name 和Category 模糊化,并根据其相关性对每一列进行了适当的提升。
我已经阅读了Ngrams,但是我真的不知道如何正确使用它。当我将NGramTokenFilter 添加到我的自定义分析器时,索引器工作。这里的问题是,我不希望每一列都使用它(只是名称和类别),并且在激活它时结果非常奇怪。
如果我将result = new NGramTokenFilter(result, 3, 4); 添加到我的分析器并搜索“nike ball”,它只会返回任何内容。
Ngrams 是这里的解决方案吗?我做错了什么?
对于如何改进产品搜索,您还有其他建议吗?
【问题讨论】:
-
你用什么样的字段来索引?
-
您应该注意,除非您使用 QueryParser,否则您的分析器不会应用于您的查询。手动构建的查询不会被分析,正如您必须自己拆分空格而不是让分析器处理这一事实所表明的那样。
标签: lucene lucene.net