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
              }
            }
          ]
        }
      }
    }
  }
}


相关文章
|
API 索引
JDK8之findAny和findFirst
JDK8之findAny和findFirst
578 0
|
搜索推荐 Java 索引
Spring Boot中的ElasticsearchRepository
Spring Boot中的ElasticsearchRepository
|
前端开发
基于若依ruoyi-nbcio支持flowable流程增加自定义业务表单(二)
基于若依ruoyi-nbcio支持flowable流程增加自定义业务表单(二)
921 1
|
存储 索引
Elasticsearch索引之嵌套类型:深度剖析与实战应用
Elasticsearch索引之嵌套类型:深度剖析与实战应用
|
存储 自然语言处理 关系型数据库
Elasticsearch 查询时 term、match、match_phrase、match_phrase_prefix 的区别
【7月更文挑战第3天】Elasticsearch 查询时 term、match、match_phrase、match_phrase_prefix 的区别
|
消息中间件 Kafka API
Kafka Exactly Once 语义实现原理:幂等性与事务消息
Apache Kafka的Exactly-Once语义确保了消息处理的准确性和一致性。通过幂等性和事务消息,Kafka实现了要么全处理要么全不处理的原子性。文章详细解析了Kafka事务的工作流程,包括生产者的幂等性(通过序列号保证),以及事务消息的提交和回滚过程。Kafka事务提供了ACID保证,但存在性能限制,如额外的RPC请求和单生产者只能执行一个事务。此外,事务适用于同集群内的操作,跨集群时原子性无法保证。了解这些原理有助于开发者更好地利用Kafka事务构建可靠的数据处理系统。
601 3
 Kafka Exactly Once 语义实现原理:幂等性与事务消息
|
SQL 存储 Java
Hive 特殊的数据类型 Array、Map、Struct
在Hive中,`Array`、`Map`和`Struct`是三种特殊的数据类型。`Array`用于存储相同类型的列表,如`select array(1, "1", 2, 3, 4, 5)`会产生一个整数数组。`Map`是键值对集合,键值类型需一致,如`select map(1, 2, 3, "4")`会产生一个整数到整数的映射。`Struct`表示结构体,有固定数量和类型的字段,如`select struct(1, 2, 3, 4)`创建一个无名结构体。这些类型支持嵌套使用,允许更复杂的结构数据存储。例如,可以创建一个包含用户结构体的数组来存储多用户信息
2725 0
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(八十)(2)
SqlAlchemy 2.0 中文文档(八十)
293 0
|
存储 API 开发工具
oss创建bucket
oss创建bucket
2426 1
|
SQL 搜索推荐 TensorFlow
【最佳实践】阿里云 Elasticsearch 向量检索4步搭建“以图搜图”搜索引擎
“图片搜索”是作为导购类网站,比较常见的一种功能,其实现的方式也有多种。但如何做到快速、精准、简单等特性,本文给你答案。
12610 1
【最佳实践】阿里云 Elasticsearch 向量检索4步搭建“以图搜图”搜索引擎

热门文章

最新文章