ES中 Nested 类型的原理和使用

简介: ES中 Nested 类型的原理和使用

1、Nested(嵌套类型)是个啥?

官方定义:官方释义:这个nested类型是object一种数据类型,允许对象数组以相互独立的方式进行索引


nested属于object类型的一种,是Elasticsearch中用于复杂类型对象数组的索引操作。Elasticsearch没有内部对象的概念,因此,ES在存储复杂类型的时候会把对象的复杂层次结果扁平化为一个键值对列表。


2、适用场景

字段值为复杂类型的情况,即字段值为非基本数据类型


3、案例

3.1 场景

假如我们有如下order索引,包含订单的商品列表

PUT /order/_doc/1
{
  "order_name": "xiaomi order",
  "desc": "shouji zhong de zhandouji",
  "goods_count": 3,
  "total_price": 12699,
  "goods_list": [
    {
      "name": "xiaomi PRO MAX 5G",
      "price": 4999
    },
    {
      "name": "ganghuamo",
      "price": 19
    },
    {
      "name": "shoujike",
      "price": 1999
    }
  ]
}
PUT /order/_doc/2
{
  "order_name": "Cleaning robot order",
  "desc": "shouji zhong de zhandouji",
  "goods_count": 2,
  "total_price": 12699,
  "goods_list": [
    {
      "name": "xiaomi cleaning robot order",
      "price": 1999
    },
    {
      "name": "dishwasher",
      "price": 4999
    }
  ]
}


3.2 需求

查询订单商品中商品名称为dishwasher并且商品价格为1999的订单信息,尝试执行以下脚本

GET order/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "goods_list.name": "dishwasher"    // 条件一
          }
        },
        {
          "match": {
            "goods_list.price": 1999           // 条件二
          }
        }
      ]
    }
  }
}


3.3 结果

按照bool中must的查询逻辑,两个条件都符合的数据并不存在,然而执行查询后发现返回以下结果

"hits" : [
      {
        "_index" : "order",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.7199211,
        "_source" : {
          "order_name" : "Cleaning robot order",
          "desc" : "shouji zhong de zhandouji",
          "goods_count" : 2,
          "total_price" : 12699,
          "goods_list" : [
            {
              "name" : "xiaomi cleaning robot order",
              "price" : 1999
            },
            {
              "name" : "dishwasher",
              "price" : 4999
            }
          ]
        }
      }
    ]


3.4 原因分析

可以看到上述结果元数据中出现了订单数据,这和预期结果不一致。

分析原因如下:

当字段值为复杂数据类型(Object、Geo-Point等)的时候,ES内部实际是以如下方式保存数据的:

{
  "order_name": "Cleaning robot order",
  "desc": "shouji zhong de zhandouji",
  "goods_count": 2,
  "total_price": 12699,
  "goods_list.name":[ "alice", "cleaning", "robot", "order", "dishwasher" ],
  "goods_list.price":[ 1999, 4999 ]
}

上述例子中goods_list中每个对象元素的属性值被扁平化存储在了数组中,此时已丢失了对应关系,因此无法保证搜索的准确。


3.5 解决方案

使用Nested类型


4、Nested用法

上述问题解决办法即对复杂类型使用Nested类型。在ES中嵌套类型不止Nested一种,但是只有Nested是单独的考点,因此其他的暂不需考虑


4.1 创建Mapping

在Mapping中为复杂类型指定Nested类型

PUT order
{
  "mappings": {
    "properties": {
      "goods_list": {
        "type": "nested",
        "properties": {
          "name": {
            "type": "text"
          }
        }
      }
    }
  }
}


4.2 写入数据

再次写入数据,此处省去此步骤代码。


4.3

执行查询,实际为query外层进行了一层嵌套。

GET /order/_search
{
  "query": {
    "nested": {
      "path": "goods_list", 
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "goods_list.name": "dishwasher"
              }
            },
            {
              "match": {
                "goods_list.price": 4999
              }
            }
          ]
        }
      }
    }
  }
}


相关文章
|
2月前
|
存储 JavaScript 索引
js开发:请解释什么是ES6的Map和Set,以及它们与普通对象和数组的区别。
ES6引入了Map和Set数据结构。Map的键可以是任意类型且有序,与对象的字符串或符号键不同;Set存储唯一值,无重复。两者皆可迭代,支持for...of循环。Map有get、set、has、delete等方法,Set有add、delete、has方法。示例展示了Map和Set的基本操作。
44 3
|
JavaScript 开发者 索引
搞懂 TypeScript 中的映射类型(Mapped Types)
搞懂 TypeScript 中的映射类型(Mapped Types)
725 0
|
10月前
ES6: Symbol概念与用法举例
ES6: Symbol概念与用法举例
31 0
|
11月前
ES5 / ES6 的继承除了写法以外还有什么区别
ES5 / ES6 的继承除了写法以外还有什么区别
ts重点学习46-接口与类型别名得异同
ts重点学习46-接口与类型别名得异同
76 0
ts重点学习46-接口与类型别名得异同
ts重点学习75-泛型约束
ts重点学习75-泛型约束
145 0
ts重点学习75-泛型约束
|
分布式计算 MaxCompute 索引
ElasticWriter-nested类型实践案例
MaxCompute表jsonArray数据使用数据集成ElasticSearch writer插件写入es,嵌套属性
225 0
ElasticWriter-nested类型实践案例
重构——18自封装字段(Self Encapsulate Field)
自封装字段(Self Encapsulate Field):你直接访问一个字段,但与字段之间的耦合关系逐渐变得笨拙;为这个字段建立取值/设置函数,并且只以这些函数来访问字段
1818 0
|
索引
ES6 - for of & for in 区别
ES6 - for of & for in 区别
113 0
|
SQL 关系型数据库 数据库
PostgreSQL 同名 index operator search_path优先级引入的一个问题 - 为啥突然不走索引了? - intarray示例
标签 PostgreSQL , intarray , ops , operator , OPERATOR , 操作符路径 , search_path , 优先级 背景 操作符是数据库最常用的要素之一,一个SQL语句中总是会出现它的影子。
1209 0