【问题标题】:Query in ElasticSearch to match part of the word在 ElasticSearch 中查询以匹配部分单词
【发布时间】:2018-11-01 19:58:45
【问题描述】:

我正在尝试在 ElasticSearch 中编写一个匹配单词中连续字符的查询。所以,如果我的索引有“John Doe”,我应该仍然会看到 Elasticsearch 返回的“John Doe”,用于以下搜索。

  1. 约翰·多伊
  2. 约翰做
  3. 哦,做
  4. 约翰
  5. 确实

到目前为止,我已经尝试过以下查询。

{
  "query": {
    "multi_match": {
      "query": "term",
      "operator": "OR",
      "type": "phrase_prefix",
      "max_expansions": 50,
      "fields": [
        "Field1",
        "Field2"
      ]
    }
  }
}

但这也会返回不必要的匹配,例如当我输入 john x 时我仍然会得到“John Doe”。

【问题讨论】:

  • 这个答案正好满足你的需要:stackoverflow.com/a/41094878/4604579
  • 我希望部分单词匹配是连续的。因此,搜索“John Do”应该只导致 John Doe,而不是 ngram 分析器正在执行的 John X Do。
  • 不,因为该解决方案使用 ngram 标记器,它标记整个输入而不是单独的术语,就像 ngram 标记过滤器那样
  • 除了 ngram 之外,我还有什么可以用来匹配我的部分连续单词匹配用例的吗?
  • 我链接到的示例完全支持您的用例。 Ngram 标记器将索引连续的单词

标签: elasticsearch


【解决方案1】:

这对我有用。 将您的数据索引为关键字,而不是 ngram。 并使用通配符正则匹配来匹配单词。

 "query": {
          "bool": {
              "should": [
                {
                  "wildcard": { "Field1": "*" + term + "*" }
                },
                {
                  "wildcard": { "Field2": "*" + term + "*" }
                }
              ],
              "minimum_should_match": 1
          }
      }

【讨论】:

  • 但请注意,根据您的索引大小,集群的性能 might suffer big time。理想情况下,应尽可能避免使用前缀通配符,因为它会强制 ES 进行全索引扫描。我将为那些拥有大索引并且无法使用带有前缀通配符的通配符查询的人提供替代解决方案。
【解决方案2】:

正如我在上面的评论中所解释的,随着索引的增长,应不惜一切代价避免使用前缀通配符,因为这将迫使 ES 进行完整的索引扫描。我仍然相信 ngrams(更准确地说是 edge-ngrams)是要走的路,所以我在下面尝试一下。

这个想法是索引输入的所有后缀,然后使用prefix query 匹配任何后缀,因为搜索前缀不会遇到与搜索后缀相同的性能问题。所以想法是索引john doe如下:

john doe
ohn doe
hn doe
n doe
doe
oe
e

这样,使用prefix 查询,我们可以匹配这些标记的任何子部分,从而有效地实现匹配部分连续单词的目标,同时确保良好的性能。

索引的定义是这样的:

PUT my_index
{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "my_analyzer": {
            "type": "custom",
            "tokenizer": "keyword",
            "filter": [
              "lowercase",
              "reverse",
              "suffixes",
              "reverse"
            ]
          }
        },
        "filter": {
          "suffixes": {
            "type": "edgeNGram",
            "min_gram": 1,
            "max_gram": 20
          }
        }
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "name": {
          "type": "text",
          "analyzer": "my_analyzer",
          "search_analyzer": "standard"
        }
      }
    }
  }
}

然后我们可以索引一个示例文档:

PUT my_index/doc/1
{
  "name": "john doe"
}

最后,以下所有搜索都将返回john doe 文档:

POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "john doe"
    }
  }
}

POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "john do"
    }
  }
}

POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "ohn do"
    }
  }
}

POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "john"
    }
  }
}

POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "n doe"
    }
  }
}

【讨论】:

    猜你喜欢
    • 2016-10-10
    • 2016-03-01
    • 2013-08-08
    • 2020-02-02
    • 2016-05-15
    • 2015-03-13
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    相关资源
    最近更新 更多