用于产品搜索的子字符串匹配

时间:2017-10-16 10:03:32

标签: lucene lucene.net

我有一个产品数据库(足球),其中包含大约5k个产品。产品搜索的Lucene索引目前包含名称,类别,颜色数字(ArtNo和EAN)。

问题的相关表示例:

| Name                   | Color            |
--------------------------------------------
| Nike Training football | red black        |
| Nike Match football    | black white      |
--------------------------------------------

对于索引我创建了一个自定义分析器,因此我可以使用其他行为扩展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无法搜索子串(除了通配符),因为它只比较令牌 - 我确实需要这样的东西。

我已使NameCategory模糊不清,并根据其相关性为每一栏提供了适当的推动。

我已经阅读了 Ngrams ,但我真的不知道如何正确使用它。将NGramTokenFilter添加到自定义分析器时,索引器可以正常工作。这里的问题是,我不希望每列(只是名称和类别),并且激活它时结果非常奇怪。

如果我将result = new NGramTokenFilter(result, 3, 4);添加到我的分析器并搜索" nike ball "它什么都不返回。

Ngrams是解决方案吗?我做错了什么?

您对如何改进产品搜索还有其他建议吗?

1 个答案:

答案 0 :(得分:0)

我'不熟悉Ngrams,但我认为你的情况有两种方法:

<强> 1。在搜索中使用通配符

在您要搜索的字段上使用前缀或模糊查询。重要的是你使用TextField( Javadoc)因为这些字段将被分析(StringField不要)并用于全文搜索。基于此,应该可以使用多个不完全匹配的术语进行搜索。

<强> 2。使用不同领域的不同分析仪

您可以使用PerFieldAnalyzerWrapper Javadoc分析具有不同分析器的不同字段。定义哪个字段应该使用哪个分析仪进行分析,然后您就可以了。 但请注意,您使用相同的分析器进行索引和搜索(它的lucene最佳实践)

其他信息

如果您使用通配符和变音符号(德语yaaaay),您必须知道不会像普通查询一样分析通配符查询。 我遇到了同样的问题并用两种方式解决了这个问题:

  • &#34;归一化&#34; (没有变音符号保存 - &gt;转换为基本拉丁语 分析器的字符)
  • &#34;非归一化&#34; (与Umlaut一起保存)

在这两个字段中搜索BooleanQuery时。