ElasticSearch的nested类型(一)

113 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

近期在工作中需要使用es进行简单的全文检索,所以最近都在边学边做笔记,也会把自己遇到的bug以及如何解决的,一并记录在这里,供大家学习参考。

1、概述

在ElsaticSearch的实战过程中,会遇到嵌套文档的形式,这个时候就涉及到nested嵌套类型。

nested类型是一种特殊的对象object数据类型,允许对象数组彼此独立的进行索引和查询。

内部对象object字段的数组不能像我们所期望的那样工作。 Lucene没有内部对象的概念,所以Elasticsearch将对象层次结构扁平化为一个字段名称和值的简单列表。

如果需要索引对象数组并维护数组中每个对象的独立性,则应使用nested数据类型而不是object数据类型。 在内部,嵌套对象将数组中的每个对象作为单独的隐藏文档进行索引,这意味着每个嵌套对象都可以使用嵌套查询nested query独立于其他对象进行查询

2、对象类型

ElasticSearch支持对象类型的存储,我们可以把一个对象数组存放到某个document的字段内。比如把订单当作doc,添加goods字段,存储该订单包含的商品。

PUT /test_order
{
  "mappings": {
    "properties": {
      "orderId" : {
        "type" : "long"
      },
      "createdTime" : {
          "type" : "date",
          "format" : "yyyy-MM-dd"
        },
        "userName" : {
        "type" : "text",
        "fields" : {
          "keyword" : {
            "type" : "keyword",
            "ignore_above" : 256
          }
        }
      },
      "goodDoc" : {
        "type" : "nested",
        "properties" : {
          "goodName" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "desc" : {
            "type" : "text",
            "analyzer" : "ik_max_word",
            "search_analyzer" : "ik_smart"
          },
          "nums" : {
            "type" : "long"
          },
          "price" : {
            "type" : "long"
          }
        }
      }
    }
  }
}

向索引中添加两组数据

{
  "took" : 533,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "test_order",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "orderId" : 100001,
          "createdTime" : "2022-05-11",
          "userName" : "用户1",
          "goodDoc" : [
            {
              "goodName" : "乐事薯片",
              "desc" : "乐事薯片-番茄风味",
              "nums" : 2,
              "price" : 15
            },
            {
              "goodName" : "瓜子",
              "desc" : "洽洽香瓜子",
              "nums" : 2,
              "price" : 28
            }
          ]
        }
      },
      {
        "_index" : "test_order",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "orderId" : 100002,
          "createdTime" : "2022-05-11",
          "userName" : "用户2",
          "goodDoc" : [
            {
              "goodName" : "麻花",
              "desc" : "黑芝麻味小麻花",
              "nums" : 3,
              "price" : 18
            },
            {
              "goodName" : "麦片",
              "desc" : "奇亚籽水果麦片",
              "nums" : 5,
              "price" : 49
            }
          ]
        }
      }
    ]
  }
}

使用查询语句对索引进项查询。

1、查询订单号为100001的订单:

GET /test_order/_search
{
  "query": {
    "match": {
      "orderId": 100001
    }
  }
}

查询结果:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "test_order",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "orderId" : 100001,
          "createdTime" : "2022-05-11",
          "userName" : "用户1",
          "goodDoc" : [
            {
              "goodName" : "乐事薯片",
              "desc" : "乐事薯片-番茄风味",
              "nums" : 2,
              "price" : 15
            },
            {
              "goodName" : "瓜子",
              "desc" : "洽洽香瓜子",
              "nums" : 2,
              "price" : 28
            }
          ]
        }
      }
    ]
  }
}

2、nested类型的查询:

GET /test_order/_search
{
  "query": {
    "nested": {
      "path": "goodDoc",
      "query": {
        "match": {
          "goodDoc.goodName": {
            "query": "麻花"
          }
        }
      }
    }
  }
}

查询结果:

{
  "took" : 27,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 2.622515,
    "hits" : [
      {
        "_index" : "test_order",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 2.622515,
        "_source" : {
          "orderId" : 100002,
          "createdTime" : "2022-05-11",
          "userName" : "用户2",
          "goodDoc" : [
            {
              "goodName" : "麻花",
              "desc" : "黑芝麻味小麻花",
              "nums" : 3,
              "price" : 18
            },
            {
              "goodName" : "麦片",
              "desc" : "奇亚籽水果麦片",
              "nums" : 5,
              "price" : 49
            }
          ]
        }
      }
    ]
  }
}