【问题标题】:How does one query an exact text-field and filter terms on another number-field in an ElasticSearch Index?如何在 ElasticSearch 索引中查询确切的文本字段并过滤另一个数字字段上的术语?
【发布时间】:2021-06-13 05:54:29
【问题描述】:

我正在尝试查询在特定文本字段 Field_Name_1 上具有匹配值的所有文档的索引,并过滤这些结果以仅显示 Field_Name_2 字段在提供的列表中具有任何数值的文档 [1 , 2, 3, 4, 5]。

我面临的问题是查询将返回与Field_Name_1 中的值有些匹配的文档,但我只需要返回与Field_Name_1 的值完全匹配的文档。通过研究,我相信我应该将 Field_Name_1 设为关键字字段,而不是文本字段,因为我永远不需要通过提供 Field_Name_1 的确切值来运行此查询。

我是否认为我需要创建一个新索引并将Field_Name_1 设置为关键字,然后重新索引?我以前没有重新索引过,所以如果我做得不好,我担心会丢失数据。有没有办法以 Field_Name_1 作为文本字段来执行此查询?

这是我尝试过的两个查询,但它们都返回相同的结果。唯一的区别是第一个查询返回的“max_score”为 9.54,而第二个查询返回的“max_score”为 0。

GET Index_Name/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "Field_Name_1": "12345-1234-1234-1234-d123f123g123"
        }
      },
      "filter": {
        "terms": {
          "Field_Name_2": [
            1,
            2,
            3,
            4,
            5
          ]
        }
      }
    }
  },
  "track_total_hits": true
}


GET Index_Name/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "match": {
             "Field_Name_1": "12345-1234-1234-1234-d123f123g123"
          }
        },
        {
          "terms": {
            "Field_Name_2": [
              1,
              2,
              3,
              4,
              5
            ]
          }
        }
      ]
    }
  },
  "track_total_hits": true
}

【问题讨论】:

  • 可以分享一下你的index和你的ES版本的映射关系吗? curl -X "GET" "localhost:9200/yourindex/_mappings"
  • @JuanCarlosAlafita 当然。 Field_Name_1 是这样的, "store_id" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } 索引的整个映射太大了,不能放在这里。

标签: amazon-web-services elasticsearch lucene kibana aws-elasticsearch


【解决方案1】:

Field_Name_1 字段应为 keyword 类型。

这是因为如果没有指定分析器,Elasticsearch 会使用 standard analyzer。您可以检查使用分析 API 生成的令牌,如下所示 -

GET /_analyze
{
  "analyzer": "standard",
  "text": "12345-1234-1234-1234-d123f123g123"
}

生成的令牌将是

{
  "tokens": [
    {
      "token": "12345",
      "start_offset": 0,
      "end_offset": 5,
      "type": "<NUM>",
      "position": 0
    },
    {
      "token": "1234",
      "start_offset": 6,
      "end_offset": 10,
      "type": "<NUM>",
      "position": 1
    },
    {
      "token": "1234",
      "start_offset": 11,
      "end_offset": 15,
      "type": "<NUM>",
      "position": 2
    },
    {
      "token": "1234",
      "start_offset": 16,
      "end_offset": 20,
      "type": "<NUM>",
      "position": 3
    },
    {
      "token": "d123f123g123",
      "start_offset": 21,
      "end_offset": 33,
      "type": "<ALPHANUM>",
      "position": 4
    }
  ]
}

要返回与Field_Name_1 的值完全匹配的文档,您可以将Field_Name_1 字段的数据类型更改为keyword 类型。

修改后的索引映射将是

{
  "mappings": {
    "properties": {
      "Field_Name_1": {
        "type": "keyword"
      }
    }
  }
}

或者,如果您没有明确定义任何映射,那么您也可以像这样修改您的搜索查询:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "Field_Name_1.keyword": "12345-1234-1234-1234-d123f123g123"   // note this
        }
      },
      "filter": {
        "terms": {
          "Field_Name_2": [
            1,
            2,
            3,
            4,
            5
          ]
        }
      }
    }
  },
  "track_total_hits": true
}

这将使用keyword 分析器而不是标准分析器(注意Field_Name_1 字段后面的“.keyword”)

【讨论】:

  • Field_Name_1 被明确定义为文本字段,但我确实有另一个字段,我定义为文本关键字,我可以使用它来代替 Field_Name_1。否则,我需要将数据重新索引到一个新的索引中,该索引具有正确的 Field_Name_1 类型。是否可以在不丢失任何数据的情况下重新索引到同名的新索引?在我的情况下,索引的名称很重要。有没有办法获取我在索引上设置的当前字段类型,这样我就可以在制作新版本时修改我需要的那些?
  • 如果我这样定义我的映射,我将如何写入关键字并搜索关键字? ``` PUT my_index_name/_mapping { "properties": { "store_id": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } ```
【解决方案2】:

我认为 ESCoder 写的是你问题的答案。

另外,

"为查询上下文中的查询计算的分数表示为 单精度浮点数"

在过滤器上下文中 不计算分数。 过滤上下文主要用于过滤结构化数据,例如 Field_Name_1 字段是否设置为“12345-1234-1234-1234-d123f123g123”?

“常用过滤器将被自动缓存 Elasticsearch,以提高性能。”

如果您需要完全匹配 Field_Name_1 的值,您可以使用过滤器作为更好的选择。

https://www.elastic.co/guide/en/elasticsearch/reference/7.11/query-filter-context.html

GET Index_Name/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "match": {
             "Field_Name_1.keyword": "12345-1234-1234-1234-d123f123g123"
          }
        },
        {
          "terms": {
            "Field_Name_2": [
              1,
              2,
              3,
              4,
              5
            ]
          }
        }
      ]
    }
  },
  "track_total_hits": true
}

【讨论】:

    猜你喜欢
    • 2022-12-13
    • 2022-01-03
    • 2023-03-26
    • 2015-07-11
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多