有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Lucene:前缀令牌匹配或精确匹配的前缀

我有几千根这样的线

  • 福吧赫普
  • 福巴德普酒店
  • 巴兹:还有别的吗

我想提供一个有效的搜索,以便

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

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

  • “herp foo”(顺序错误,不重要)
  • “foo blerp”(并非所有代币)
  • “murp herp”(并非所有代币)

不要

也就是说,精确的前缀匹配和正确顺序的标记(可能是前缀)匹配都应该匹配,与大小写无关,但查询中的所有标记都必须在文档中

我已经使用一个StandardAnalyzer和一个带有前缀查询的公共QueryParser设置了典型的Lucene示例

我想我可能需要一个BinaryQuery来声明我需要查询中的所有标记都出现在文档中,但我不能完全弄清楚如何获取标记来构建它(查询由用户提供)。我还意识到,使用StringField而不是TextField可以提供与令牌匹配相反的精确字符串匹配,但我不确定这是否是我可以与上述内容结合使用的内容

我该怎么做?我甚至不需要用Lucene来做这件事,但它看起来很合适


共 (1) 个答案

  1. # 1 楼答案

    第一个(非关键)有点棘手,但要确保在所有结果中找到查询中的所有术语,只需将所有查询术语设置为必需。您可以使用添加的plus运算符来执行此操作:

    • +foo +bar
    • +foo +ba*(如果你想处理前缀,你需要添加通配符来指定它,或者可能使用ngram标记器,或者类似的东西)
    • 等等

    或者,您可以使用^{}将默认运算符设置为AND

    queryParser.setDefaultOperator(StandardQueryConfigHandler.Operator.AND);
    

    herp foofoo herp的情况下,我认为短语slop可能会让你达到你需要的地方。交换术语顺序会增加两个距离,因此:

    • "foo herp"~2:匹配“Foo-Bar-Herp”
    • "herp foo"~2:没有

    但是短语查询不支持通配符,所以如果需要将通配符与前缀词结合使用,就会遇到问题

    如果您想在不改变顺序的情况下允许更多的slop,那么我相信您已经超出了QueryParser表达查询的能力,需要转到SpanQueryAPI来手动构造查询

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

    SpanQuery term1 = new SpanTermQuery(new Term("content", "foo"));
    SpanQuery term2Prefix = new SpanMultiTermQueryWrapper(new PrefixQuery(new Term("content", "her")));
    SpanQuery finalQuery = new SpanNearQuery(new SpanQuery[] {term1, term2Prefix}, 5, true);
    

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