【问题标题】:Lucene query: bla~* (match words that start with something fuzzy), how?Lucene查询:bla~*(匹配以模糊开头的单词),怎么做?
【发布时间】:2011-02-07 12:59:18
【问题描述】:

在 Lucene 查询语法中,我想将 * 和 ~ 组合在一个有效的查询中,类似于: bla~* //无效查询

含义:请匹配以“bla”或类似“bla”开头的单词。

更新: 我现在所做的,适用于少量输入,使用以下(SOLR 模式的 sn-p):

<fieldtype name="text_ngrams" class="solr.TextField">
  <analyzer type="index">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
  </analyzer>
  <analyzer type="query">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="0"/>
        <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>

如果您不使用 SOLR,则执行以下操作。

Indextime:通过创建一个包含我的(短)输入的所有前缀的字段来索引数据。

搜索时间:仅使用 ~ 运算符,因为前缀明确存在于索引中。

【问题讨论】:

    标签: lucene wildcard fuzzy-search


    【解决方案1】:

    在 lucene 的开发主干(尚未发布)中,有代码通过 AutomatonQuery 支持此类用例。警告:API 可能/将会在发布之前发生变化,但它会为您提供思路。

    这是您的案例的示例:

    // a term representative of the query, containing the field. 
    // the term text is not so important and only used for toString() and such
    Term term = new Term("yourfield", "bla~*");
    
    // builds a DFA that accepts all strings within an edit distance of 2 from "bla"
    Automaton fuzzy = new LevenshteinAutomata("bla").toAutomaton(2);
    
    // concatenate this DFA with another DFA equivalent to the "*" operator
    Automaton fuzzyPrefix = BasicOperations.concatenate(fuzzy, BasicAutomata.makeAnyString());
    
    // build a query, search with it to get results.
    AutomatonQuery query = new AutomatonQuery(term, fuzzyPrefix);
    

    【讨论】:

    • 我刚回到这个问题,又看到了你的回答。你试过了吗?我现在正在做的(适用于小输入)是生成我输入的所有前缀并将前缀放入索引中。然后我只需要使用 ~ 运算符,并获得像 ~* 这样的功能
    • 您的解决方法适用于小输入...但正如您所暗示的,对于大输入来说将是一个问题:您将为所有这些前缀添加大量术语和帖子...这个将使 Lucene 4.0 之前的模糊查询变得更慢,因为它对所有术语进行线性扫描。
    • 是否有 Lucene 查询语法让您无需编码即可通过 Solr 访问 Automaton 查询?
    【解决方案2】:

    我不相信 Lucene 支持这样的东西,我也不相信它有一个简单的解决方案。

    “模糊”搜索不会对固定数量的字符进行操作。例如,bla~ 可能与 blah 匹配,因此它必须考虑整个术语。

    您可以做的是实现一个查询扩展算法,将查询 bla~* 转换为一系列 OR 查询

    bla* OR blb* OR blc OR .... etc.
    

    但这真的只有当字符串很短或者你可以根据一些规则缩小扩展时才可行。

    或者,如果前缀的长度是固定的,您可以添加一个带有子字符串的字段并对其执行模糊搜索。这会给你你想要的,但只有当你的用例足够狭窄时才会起作用。

    你没有具体说明为什么需要这个,也许这样做会引出其他解决方案。

    我能想到的一个场景是处理不同形式的单词。例如。找到carcars

    这在英语中很容易,因为有可用的词干分析器。在其他语言中,即使不是不可能,也很难实现词干分析器。

    但是,在这种情况下,您可以(假设您可以访问一本好字典)查找搜索词并以编程方式扩展搜索以搜索该词的所有形式。

    例如对cars 的搜索将转换为car OR cars。这已在至少一个搜索引擎中成功应用于我的语言,但显然实现起来并非易事。

    【讨论】:

    • Althug 模糊搜索不能对固定数量的字符进行操作,对于我来说,简单地使用 ~ 不会起作用(字符数差异很大)。我想匹配例如Sunla 到 Sundlaugarvegur。
    • 当然,如果我可以告诉 lucene 只匹配索引中每个单词的前 x 个字符,使用 ~ 就可以了...
    • 这里你需要超越 Lucene,使用 Levenstein、Jaro-Winkler 等字符串比较算法(qv. 下面)
    【解决方案3】:

    这是一个地址搜索服务,我想根据部分输入和可能输入错误的街道名称/城市名称/等(任何组合)来建议地址。 (想想 ajax,用户在文本字段中输入部分街道地址)

    对于这种情况,建议的查询扩展可能不太可行,因为部分字符串(街道地址)可能变得比“短”长:)

    标准化

    我能想到的一种可能性是使用字符串“规范化”,而不是模糊搜索,并将其与通配符查询简单地结合起来。

    的街道地址

    "miklabraut 42, 101 reykjavík",标准化后将变为"miklabrat 42 101 rekavik"

    所以,像这样构建索引

    1) 使用包含“标准化”版本的街道名称、城市名称等的记录构建索引,每个文档有一个街道地址(1 个或多个字段)。

    然后像这样搜索索引

    2) 规范化用于形成查询(即mik rek)的输入字符串(例如mikl reyk)。 3) 使用通配符 op 执行搜索(即mik* AND rek*),将模糊部分排除在外。

    只要归一化算法足够好,那会飞:)

    【讨论】:

      【解决方案4】:

      您的意思是您希望结合通配符和模糊查询?您可以使用带有 OR 条件的布尔查询进行组合,例如:

      BooleanQuery bq = new BooleanQuery();
      
      Query q1 = //here goes your wildcard query
      bq.Add(q1, BooleanClause...)
      
      Query q2 = //here goes your fuzzy query
      bq.Add(q2, BooleanClause...)
      

      【讨论】:

      • 我不相信这会完成 OP 的要求,因为它基本上会变成“bar~ OR bar*”,这与“bar~*”不同并且不会找到(对于例如)“brafoo”。
      • 是的,这不是我想要的:)
      • 好的,感谢您的澄清,我使用的一种方法(用于匹配蛋白质名称等)使用像 Smith-Waterman、Jaro-Winkler 等字符串距离。像 SimMetrics 这样的工具可能会有所帮助dcs.shef.ac.uk/~sam/simmetrics.html
      • 这是我第二次听说 SimMetrics,也许是时候试一试了 :) 谢谢
      猜你喜欢
      • 2015-01-10
      • 1970-01-01
      • 2014-10-01
      • 2012-12-15
      • 1970-01-01
      • 1970-01-01
      • 2013-12-07
      • 1970-01-01
      • 2010-10-01
      相关资源
      最近更新 更多