【问题标题】:Find documents that match whole query in elasticsearch在弹性搜索中查找与整个查询匹配的文档
【发布时间】:2018-11-30 10:43:16
【问题描述】:

我想在 ElasticSearch 中编写查询,该查询提供的结果包含搜索查询中的所有单词,但不仅作为完整单词,而且作为子单词。例如,如果我有具有以下值的 Document:

{
"first_name":"didier",
"last_name":"drogba"
}

我搜索“didi dro”,应该返回这个文件。如果我搜索“david drogba”,文档应该被忽略,因为它不包含单词“david”,即使是子词。 我使用 ngram tokenizer 进行了尝试,但无法达到我想要的效果。

我创建的索引

PUT doctors
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "ngram"
        }
      }
    }
  }
}

然后添加映射

put doctors/_doc/_mapping 
{
  "properties": {
    "first_name": {
      "type": "text",
      "analyzer": "my_analyzer"
    },
    "last_name": {
      "type": "text",
      "analyzer": "my_analyzer"
    }
  }
}

添加一些文档

post doctors/_doc/1
{
  "first_name": "dito",
  "last_name": "janelidze",
  "specialism": "oftalmologist",
  "location_name":"evex saburtalo clinic",
  "brand": "Evex",
  "address":"kavtaradze street N21"
}

我的搜索查询看起来像这样

get doctors/_doc/_search
{
  "query": {
    "multi_match": {
        "query": "david jane",
        "fields": ["first_name", "last_name"]
    }
  }
}

它给了我我插入的文档,但我不需要它,因为它不包含单词“david”

【问题讨论】:

  • 您能分享您尝试过的查询吗?这可以使用 Ngram Tokenizer。所需要的只是一个带有两个match 子句(first_name 和last_name 各一个)的bool must 查询。
  • 我已经更新了我的问题,添加了一些来自 kibana 的命令,希望你明白 ai 到底想要实现什么
  • 为您的多重匹配查询添加参数"operator": "and"

标签: elasticsearch search


【解决方案1】:

每个单词的运算符“和”+1。使用这个,为我工作(也可以用于自动完成)。

settings:
    analysis": {
          "filter": {
            "name_ngrams": {
              "max_gram": "20",
              "type": "edgeNGram",
              "min_gram": "1",
              "side": "front"
            }
          },
          "analyzer": {
            "partial_name": {
              "type": "custom",
              "filter": [
                "lowercase",
                "name_ngrams",
                "standard",
                "asciifolding"
              ],
              "tokenizer": "standard"
            },
            "full_name": {
              "type": "custom",
              "filter": [
                "standard",
                "lowercase",
                "asciifolding"
              ],
              "tokenizer": "standard"
            }
          }


mapping:

    "first_name": {

        "type": "text",
        "index_analyzer": "partial_name",
        "search_analyzer": "full_name"

    },
    "last_name": {

        "type": "text",
        "index_analyzer": "partial_name",
        "search_analyzer": "full_name"

    },

【讨论】:

    【解决方案2】:

    第 1 点:映射变化

    N-Gram tokenizer 将从输入单词构造指定 length 的单词。此长度在映射中指定为min_grammax_gram,如果您不指定,则默认分别为12

    我已经分别用min_gram:3max_gram:5 更新了您提供的映射。

    N-Gram Tokenizer 然后将创建令牌,例如对于didier,它们将是did, idi, die, ier, didi, idie, dier, didie, idier,最终存储在倒排索引中。

    默认 1 和 2 分别为 min_grammax_gram,请注意 didierdavid 会将 id 作为公共子词,这就是返回它们的原因。


    映射

    PUT doctors
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "tokenizer": "my_tokenizer"
            }
          },
          "tokenizer": {
            "my_tokenizer": {
              "type": "ngram",
              "min_gram": 3,
              "max_gram": 6,
            }
          }
        }
      }
    }
    

    第 2 点:查询变更

    也就是说,尽管进行了映射更改,但如果您的查询字符串使用您所拥有的 david jane,它将在 first_namelast_name 中搜索 david or jane。这意味着文档dito janelidze 仍将被返回(但分数将低于具有david jane 的文档)

    使用运算符AND 会使搜索成为david AND jane 中的first_namelast_name,这不是您要查找的内容。

    您可以做的是利用下面的布尔查询创建另一个名为name的字段,使用copy_to字段复制first_namelast_name的值到它使用该字段进行搜索。


    查询

    POST <your_index_name>/_search
    {
      "query": {
        "bool":{
          "must": [
            {
              "match": {
                "first_name": "david"
              }
            },
            {
              "match": {
                "last_name": "jane"
              }
            }
          ]
        }
      }
    }
    

    不幸的是,您需要删除、重新创建索引并再次提取文档,因为所需的更改是在映射级别。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-01
      • 1970-01-01
      • 2014-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      相关资源
      最近更新 更多