首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在elasticsearch中查找与整个查询匹配的文档

在elasticsearch中查找与整个查询匹配的文档
EN

Stack Overflow用户
提问于 2018-11-30 18:43:16
回答 2查看 56关注 0票数 0

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

代码语言:javascript
复制
{
"first_name":"didier",
"last_name":"drogba"
}

并且我搜索“滴滴滴滴”,这个文档应该会被返回。如果我搜索"david drogba",那么document应该被忽略,因为它没有包含单词"david“,甚至连子单词都没有。我尝试使用ngram标记器,但无法达到我想要的效果。

我创建的索引

代码语言:javascript
复制
PUT doctors
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "ngram"
        }
      }
    }
  }
}

然后添加了映射

代码语言:javascript
复制
put doctors/_doc/_mapping 
{
  "properties": {
    "first_name": {
      "type": "text",
      "analyzer": "my_analyzer"
    },
    "last_name": {
      "type": "text",
      "analyzer": "my_analyzer"
    }
  }
}

添加一些文档

代码语言:javascript
复制
post doctors/_doc/1
{
  "first_name": "dito",
  "last_name": "janelidze",
  "specialism": "oftalmologist",
  "location_name":"evex saburtalo clinic",
  "brand": "Evex",
  "address":"kavtaradze street N21"
}

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

代码语言:javascript
复制
get doctors/_doc/_search
{
  "query": {
    "multi_match": {
        "query": "david jane",
        "fields": ["first_name", "last_name"]
    }
  }
}

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

EN

回答 2

Stack Overflow用户

发布于 2018-11-30 20:05:56

+1对于运算符“和”对于每个words.Use this,对我都有效(也可以用于自动补全)。

代码语言:javascript
复制
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"

    },
票数 1
EN

Stack Overflow用户

发布于 2018-11-30 20:14:46

要点1:映射更改

-Gram tokenizer将从输入单词中构造指定长度的单词。此长度被指定为映射中的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作为公共子字,这就是返回它们的原因。

映射

代码语言:javascript
复制
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_name OR last_name中搜索david or jane。这意味着仍然会返回文档dito janelidze (但得分低于具有david jane的文档)

使用运算符AND将在first_namelast_name中作为david AND jane进行搜索,这不是您要查找的内容。

相反,您可以使用下面的布尔查询或创建另一个名为name的字段,使用copy_to字段将first_namelast_name的值复制到该字段中,并使用该字段进行搜索。

查询

代码语言:javascript
复制
POST <your_index_name>/_search
{
  "query": {
    "bool":{
      "must": [
        {
          "match": {
            "first_name": "david"
          }
        },
        {
          "match": {
            "last_name": "jane"
          }
        }
      ]
    }
  }
}

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

希望这能有所帮助!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53555900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档