GET查询,加.keyword与不加.keyword的区别是什么,为什么没有结果

GET production-index-info/index_info/_search
{
  "query": {
    "bool": {
      "minimum_should_match": 0,
      "must": [
        {
          "term": {
            "is_resolved.keyword": "解决"
          }
        }
      ],
      "should": []
    }
  }
}

使用这种方式查询,就可以得到数据。数据如下格式

{
  "took": 51,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2914867,
    "max_score": 0.26003557,
    "hits": [
      {
        "_index": "production-index-info",
        "_type": "index_info",
        "_id": "5a5d4fcdc42fbc2bcefae14a",
        "_score": 0.26003557,
        "_source": {
          "created_time": "2020-01-21T22:44:50+08:00",
          "tickets": [],
          "is_resolved": "解决",
          "note": "",
        }
      },
      {
        "_index": "production-index-info",
        "_type": "index_info",
        "_id": "5a64a762cd1cb23dbb294bfa",
        "_score": 0.26003557,
        "_source": {
          "created_time": "2018-01-21T22:44:50+08:00",
          "tickets": [],
          "is_resolved": "解决",
          "note": "",
        }
      },
      {
        "_index": "production-index-info",
        "_type": "index_info",
        "_id": "5a5d88136817b27825831ac2",
        "_score": 0.26003557,
        "_source": {
          "created_time": "2018-01-16T13:05:23+08:00",
          "tickets": [],
          "is_resolved": "解决",
          "note": "11111",
        }
      },
      {
        "_index": "production-index-info",
        "_type": "index_info",
        "_id": "5a5dbc30c42fbc2ef1307ba9",
        "_score": 0.26003557,
        "_source": {
          "created_time": "2018-01-16T16:47:44+08:00",
          "tickets": [],
          "is_resolved": "未解决",
          "note": "222",
        }
      },
      ......
    ]
  }
}

但是如果使用这种方式,删除了.keywprd

GET production-index-info/index_info/_search
{
  "query": {
    "bool": {
      "minimum_should_match": 0,
      "must": [
        {
          "term": {
            "is_resolved": "解决"
          }
        }
      ],
      "should": []
    }
  }
}

那么结果就是这样的

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 0,
    "max_score": null,
    "hits": []
  }
}

我知道这个.keyword和分词有关,但是对于这个例子,没有搞懂为什么,加了.keyword才可以查询出来结果,不加就不行了。另外,is_resolved的值,只有解决和未解决两个。

阅读 32k
3 个回答

1.ES5.0及以后的版本取消了string类型,将原先的string类型拆分为textkeyword两种类型。它们的区别在于text会对字段进行分词处理而keyword则不会。
2.当你没有以IndexTemplate等形式为你的索引字段预先指定mapping的话,ES就会使用Dynamic Mapping,通过推断你传入的文档中字段的值对字段进行动态映射。例如传入的文档中字段price的值为12,那么price将被映射为long类型;字段addr的值为"192.168.0.1",那么addr将被映射为ip类型。然而对于不满足ip和date格式的普通字符串来说,情况有些不同:ES会将它们映射为text类型,但为了保留对这些字段做精确查询以及聚合的能力,又同时对它们做了keyword类型的映射,作为该字段的fields属性写到_mapping中。例如,当ES遇到一个新的字段"foobar": "some string"时,会对它做如下的Dynamic Mapping:

{
    "foobar": {
        "type" "text",
        "fields": {
            "keyword": {
                "type": "keyword",
                "ignore_above": 256
            }
        }
    }
}

在之后的查询中使用foobar是将foobar作为text类型查询,而使用foobar.keyword则是将foobar作为keyword类型查询。前者会对查询内容做分词处理之后再匹配,而后者则是直接对查询结果做精确匹配。
3.ES的term query做的是精确匹配而不是分词查询,因此对text类型的字段做term查询将是查不到结果的(除非字段本身经过分词器处理后不变,未被转换或分词)。此时,必须使用foobar.keyword来对foobar字段以keyword类型进行精确匹配。

一般情况下,keyword是对字段进行精确匹配,但对于keyword=解决 搜出 已解决 的情况,需要你贴出mapping来进一步分析了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏