Lucene:前缀标记匹配或完全匹配的前缀

时间:2014-12-19 13:51:57

标签: java lucene

我有几千个看起来像这样的字符串

  • Foo-Bar-Herp
  • 富-BAR-DERP
  • Baz-Blurb还有别的东西

我想提供一个有效的搜索

  • “foo bar”(标记化前缀)
  • “foo herp”(跳过令牌)
  • “foo-bar-”(确切的前缀)
  • “Bar-Herp”(中间的确切字符串)
  • “foo ba”(一个完整的标记和另一个标记的前缀)

等。 全部返回第一个字符串(可能还有其他字符串),但

  • “herp foo”(错误的订单,不严格)
  • “foo blerp”(并非所有令牌)
  • “murp herp”(不是所有代币)

不要。

即。正确的前缀匹配和令牌(可能的前缀)匹配的顺序应该匹配,与大小写无关,但查询中的所有标记必须在文档中。

我使用StandardAnalyzer和带有前缀查询的常见QueryParser设置了典型的Lucene示例。

我想我可能需要一个BinaryQuery来声明我需要查询中的所有令牌都在文档中,但我无法想象得到令牌来构建它(查询是用户提供的)。我也意识到使用StringField而不是TextField给了我精确的字符串匹配而不是令牌智能匹配,但是我不确定这是否可以与上面的内容结合起来?

我应该怎么做?我甚至不必使用Lucene来做它,但它看起来很合适。

1 个答案:

答案 0 :(得分:1)

您的第一个(非关键)有点棘手,但为了确保查询中的所有术语都可以在所有结果中找到,您可以简单地制作所需的所有查询术语。您可以使用添加的加号运算符执行此操作:

  • +foo +bar
  • +foo +ba*(如果你想处理前缀,你需要添加通配符来指定它,或者可能使用ngram tokenizer,或者其他一些)

或者,您可以使用StandardQueryParser.setDefaultOperator

将默认运算符设置为AND
queryParser.setDefaultOperator(StandardQueryConfigHandler.Operator.AND);

herp foo vs foo herp的情况下,我认为短语slop可能会让你到达你需要的位置。交换术语的顺序将增加两个距离,所以:

  • "foo herp"~2:匹配" Foo-Bar-Herp"
  • "herp foo"~2:不

短语查询不支持通配符,因此如果您需要将其与前缀术语结合使用,则会遇到问题。

如果您希望在没有更改订单的情况下允许更多的slop,那么我相信您超出了QueryParser表达查询的能力,并且需要转到{{1}用于手动构建查询的API。

手动构建查询,您可以执行以下操作:

SpanQuery

按顺序查找第一个术语(完全匹配)和第二个术语的前缀,它们之间不超过五个术语。