Elasticsearch匹配查询多词不精确词

时间:2020-01-02 11:37:37

标签: elasticsearch nodes

我是弹性搜索的新手,我很累在索引文档中查找数据。就像我有4个文档,并且在2个字段中fullName, userName-

{
    "_index": "users",
    "_type": "users",
    "_id": "NwV2GG8BmEFrScbl3IE8",
    "_score": 1,
    "_source": {
        "fullName": "Max Payne",
        "id": 1,
        "userName": "MaxP"
    }
},
{
    "_index": "users",
    "_type": "users",
    "_id": "MgV2GG8BmEFrScbl3IE8",
    "_score": 1,
    "_source": {
        "fullName": "Thomas John",
        "id": 6,
        "userName": "ThomesJ"            
    }
},
{
    "_index": "users",
    "_type": "users",
    "_id": "MgD2TG1BmEFrrfbs3RT9",
    "_score": 1,
    "_source": {
        "fullName": "John well",
        "id": 7,
        "userName": "ThomesW"
    }
},
{
    "_index": "users",
    "_type": "users",
    "_id": "QwR58DTBmEFrScbl8op4",
    "_score": 1,
    "_source": {
        "fullName": "Max smith",
        "id": 1,
        "userName": "MaxS"
    }
}

如果搜索 情况1 “马”然后我需要3个文档

案例2 'Max',那么我需要2个文档

案例3 'Max s',那么我需要1个文档(Max Smith) “ Max p”,那么我需要1个文档(Max Payne)

情况4 '约翰',那我需要2个文件

我尝试使用此方法,如果完整字符串匹配,则找到数据,否则找不到数据。

"bool" : {
    "should": {
        "query_string": {
        "query": '*'+keyword+'*', // "query": keyword+'*',
        "fields": [ "fullName", "userName" ]
        },
    },
}

此外,我尝试了一下,但没有用

"term": {
    "fullName": {
    "value": keyword
  }
}

我将Elasticsearch 6.3用于NodeJs客户端

3 个答案:

答案 0 :(得分:0)

Elasticsearch的工作原理与您在这里可能期望的根本不同。使用您使用的默认分析器,索引字段中的每个单词都成为可搜索的令牌。

使用通配符查询(https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-wildcard-query.html)可以按令牌的一部分进行搜索。但是,强烈建议不要盲目使用通配符查询,因为它们不能随着索引的增长而很好地扩展。

如果绝对需要按您描述的那样按令牌的一部分进行搜索,则应检出 n-gram 令牌过滤器(https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-ngram-tokenfilter.html)。 这会产生类似[m,a,x,ma,ax]的标记,使您可以搜索“ ma”。 这是一个实现ngram-filter的示例:

PUT so_example
{
  "settings": {
    "analysis": {
      "analyzer": {
        "ngram-example": {
          "tokenizer": "standard",
          "filter": [
            "ngram"
          ]
        }
      }
    }
  },
  "mappings": {
    "users": {
      "properties": {
        "userName": {
          "type": "text",
          "analyzer": "ngram-example"
        },
        "fullName": {
          "type": "text",
          "analyzer": "ngram-example"
        }
      }
    }
  }
}

这将允许您像执行搜索一样

GET so_example/_search
{
  "query": {
    "multi_match": {
      "query": "Max Pa",
      "type": "phrase",
      "fields": [
        "fullName"
      ]
    }
  }
}

对于以“ Max P”为例的示例,请记住要搜索2个令牌,因为从技术上讲它们是2个单词。要搜索需要以给定顺序排列的令牌,您需要 phrase_match 查询(https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html)。否则,搜索词P不需要在搜索字段中跟随Max。

答案 1 :(得分:0)

您需要尝试此查询并根据您的不同情况使用通配符,您将获得所需的预期结果

{
  "query": {
    "wildcard": {
      "fullName": {
        "value": "keyword"
      }
    }
  }
}

对于情况1:“值”:“ * ma *” 情况2:“ value”:“ max”,并且类似。

希望这会有所帮助。

答案 2 :(得分:0)

使用一个名为“ search_name”的新属性,其中将存储用户名和全名。 'copy_to'将有助于实现这一目标。

按如下所示更改索引-

PUT user_index
{
  "settings": {
    "number_of_shards": 1,
    "analysis": {
      "filter": {
        "edge_filter": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 50
        }
      },
      "analyzer": {
        "lowercase": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": [
            "trim",
            "lowercase"
          ]
        },
        "userName_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",

            "edge_filter"
          ]
        },
        "fullName_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",

            "edge_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "userName": {
        "type": "text",
        "analyzer": "userName_analyzer",
        "search_analyzer": "standard",
        "copy_to": "search_name"
      },
      "fullName": {
        "type": "text",
        "analyzer": "fullName_analyzer",
        "search_analyzer": "standard",
        "copy_to": "search_name"
      },
      "search_name":{
        "type": "text",
        "analyzer": "fullName_analyzer",
        "search_analyzer": "standard"
      }
    }
  }
}

现在使用如下所示的搜索查询-

GET user_index/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "search_name":{
              "query": "max p",
              "operator" : "and"
            }
          }
        }
      ]
    }
  }
}

请根据给出的要求更改查询值。 希望这会有所帮助。