弹性搜索模糊短语

时间:2016-08-07 17:54:27

标签: elasticsearch

我有以下查询为我的搜索添加模糊性。但是,我现在意识到匹配查询不考虑搜索字符串中单词的顺序,就像match_phrase那样。但是,我不能得到match_phrase给我模糊的结果。有没有办法告诉匹配考虑单词之间的顺序和距离?

{
    "query": {
        "match": {
            "content": {
                "query": "some search terms like this",
                "fuzziness": 1,
                "operator": "and"
            }
        }
    }
}

4 个答案:

答案 0 :(得分:15)

最终发现我需要使用span个查询的组合,这些查询可以对模糊性和污点进行大量微调。我需要添加一个函数来手动标记我的短语并添加到"子句"以编程方式编译数组:

{"query":
{
  "span_near": {
    "clauses": [
      {
        "span_multi": {
          "match": {
            "fuzzy": {
              "content": {
                "fuzziness": "2",
                "value": "word"
              }
            }
          }
        }
      },
      {
        "span_multi": {
          "match": {
            "fuzzy": {
              "content": {
                "fuzziness": "2",
                "value": "another"
              }
            }
          }
        }
      }                   
    ],
    "slop": 1,
    "in_order": "true"

答案 1 :(得分:1)

@econgineer优秀的帖子。

我想尝试使用我们正在处理的ES查询 - 但是我懒得继续使用JSON数据....

我认为这段代码有效...奇怪的是它导致jq抱怨,但ElasticSearch工作......

import json
import pprint
from collections import defaultdict
nested_dict = lambda: defaultdict(nested_dict)
query=nested_dict()
query['span_near']['clauses']=list()
query['slop']='1'
query['in_order']="true"


words=['what','is','this']
for w in words:
    nest = nested_dict()
    nest["span_multi"]["match"]["fuzzy"]["msg"]["fuzziness"]["value"]=w
    nest["span_multi"]["match"]["fuzzy"]["msg"]["fuzziness"]["fuzziness"]="2"
    json.dumps(nest)
    query['span_near']['clauses'].append(json.loads(json.dumps(nest)))


pprint.pprint(json.loads(json.dumps(query)))

如果你通过

来美化输出
cat t2.json | tr  "\'" "\""  | jq '.'

您应该看到类似

的内容
{
  "in_order": "true",
  "slop": "1",
  "span_near": {
    "clauses": [
      {
        "span_multi": {
          "match": {
            "fuzzy": {
              "msg": {
                "fuzziness": {
                  "fuzziness": "2",
                  "value": "what"
                }
              }
            }
          }
        }
      },
      {
        "span_multi": {
          "match": {
            "fuzzy": {
              "msg": {
                "fuzziness": {
                  "fuzziness": "2",
                  "value": "is"
                }
              }
            }
          }
        }
      },
      {
        "span_multi": {
          "match": {
            "fuzzy": {
              "msg": {
                "fuzziness": {
                  "fuzziness": "2",
                  "value": "this"
                }
              }
            }
          }
        }
      }
    ]
  }
}

然后查询ES它只是一个普通的

curl --silent My_ES_Server:9200:/INDEX/_search -d @t2.json

非常感谢您的初步指导,我希望其他人能够发现这一点。

答案 2 :(得分:0)

确实,一个很好的问答。 我很惊讶这种“模糊短语匹配”没有开箱即用的支持。

这是一个经过测试的NodeJS代码,它在多搜索(msearch)的上下文中生成模糊短语匹配(多子句)查询块,但是对于单个搜索,它应该是相同的。

<强>用法:

let queryBody = [];
client.msearch({
   body: queryBody
})

queryBody.push({ index: 'YOUR_INDEX' });
queryBody.push(createESFuzzyPhraseQueryBlock('YOUR PHRASE', 'YOUR_FIELD_NAME', 2));   // 2 <- fuzziness

功能:

const createESFuzzyPhraseClauseBlock = (word, esFieldName, fuzziness) => {
    let clauseBlock = JSON.parse(
        `{
            "span_multi": {
                "match": {
                    "fuzzy": {
                        "${esFieldName}": {
                            "fuzziness": "${fuzziness}",
                            "value": "${word}"
                        }
                    }
                }
            }
        }`);

    return clauseBlock;
};


const createESFuzzyPhraseQueryBlock = (phrase, esFieldName, fuzziness) => {
    let clauses = [];

    let words = phrase.split(' ');
    words.forEach(word => clauses.push(createESFuzzyPhraseClauseBlock(word, esFieldName, fuzziness)));

    let queryBlock =
        {
            "query":
                {
                    "span_near": {
                        "clauses": clauses,
                        "slop": 1,
                        "in_order": "true"
                    }
                }
        };

    return queryBlock;
};

答案 3 :(得分:0)

还考虑混合查询,对我来说基本查询看起来像这样-对于长度为2的短语,我使用了前缀查询,对于其余部分,我使用了模糊性设置为AUTO的匹配查询。