Elasticsearch 复杂类型 Nested

这篇具有很好参考价值的文章主要介绍了Elasticsearch 复杂类型 Nested。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

复杂类型

建模到底是个什么东东?

建模解决什么问题?

复杂类型的的检索问题

Nested

主要解决复杂类型无法搜索的问题

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

扁平化处理带来的问题

正常如果我们不使用Nested对象时es会如下处理这个结构:

PUT my-index-000001/_doc/1
{
  "group" : "fans",
  "user" : [ 
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}
上面的文档被创建之后,user数组中的每个json对象会以下面的形式存储
{
  "group" :        "fans",
  "user.first" : [ "alice", "john" ],
  "user.last" :  [ "smith", "white" ]
}

如我们上面定义的user对象它包含first和last属性,我们检索时可能是想要first=xx and last=xxx,

如果扁平化处理就会失去这个逻辑关系

它会去找 "user.first" : [ "alice", "john" ],

然后OR上"user.last" : [ "smith", "white" ]

创建Nested

PUT <index_name>
{
  "mappings": {
    "properties": {
      "<nested_field_name>": {
        "type": "nested"
      }
    }
  }
}

查询nested

GET <index_name>/_search
{
  "query": {
    "nested": {
      "path": "<nested_field_name>",
      "query": {
        ...
      }
    }
  }
}

Nested可选参数

path:nested对象的查询深度.通俗点来讲就是你不断的点出来那个属性位置

score_mode:评分计算方式,这指的是多个检索字段都有评分的话怎么合成一个总评分的规则

  • avg (默认):使用所有匹配的子对象的平均相关性得分。
  • max:使用所有匹配的子对象中的最高相关性得分。
  • min:使用所有匹配的子对象中最低的相关性得分。
  • none:不要使用匹配的子对象的相关性分数。该查询为父文档分配得分为0。
  • sum:将所有匹配的子对象的相关性得分相加。

Nested测试

测试: 非nested索引

创建
DELETE test_idx_nested
PUT test_idx_nested
{
  "mappings": {
    //设置mapping的属性(字段)
    "properties":{
      "goods_list":{
        //如果它是一个复杂类型还有其他字段同样通过properteis设置
        "properties":{
          //属性1名称
          "name":{
            //定义属性必须有类型
            "type":"text",
            //根据需要是否需要定义 analyzer
            "analyzer":"ik_max_word",
            //是否定义子字段,一直不明白子字段的用户
            //定义字段的keyword,用子字段形式定义
            "fields":{
              "name_sub_field_keyword":{
                "type":"keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
} 
插入测试数据
PUT /test_idx_nested/_doc/1
{
  "order_name": "小米10 Pro订单",
  "desc": "shouji zhong de zhandouji",
  "goods_count": 3,
  "total_price": 12699,
  "goods_list": [
    {
      "name": "小米10 PRO MAX 5G",
      "price": 4999
    },
    {
      "name": "钢化膜",
      "price": 19
    },
    {
      "name": "手机壳",
      "price": 1999
    }
  ]
}
PUT /test_idx_nested/_doc/2
{
  "order_name": "扫地机器人订单",
  "desc": "shouji zhong de zhandouji",
  "goods_count": 2,
  "total_price": 12699,
  "goods_list": [
    {
      "name": "小米扫地机器人儿",
      "price": 1999
    },
    {
      "name": "洗碗机",
      "price": 4999
    }
  ]
}
查询测试
GET test_idx_nested/_search
{
  "query": {
    "bool": {
      //must必须都满足这个查询预期应该没有结果,但是实际查询出来了
      //可以猜测为什么?
      "must": [
        {
          "match": {
            "goods_list.name": "洗碗机"
          }
        },
        {
          "match": {
            "goods_list.price": "1999"
          }
        }
      ]
    }
  }
}
预期查询结果

一般不应该查出来的却查出来了就是因为分词
当然也可能是因为扁平化

如何验证是否被分词了?
GET _analyze
{
  "text": ["小米10 Pro订单"],
  "analyzer": "ik_max_word"
}

测试: Nested索引

创建
PUT test_idx_nested
{
  "mappings": {
    "properties": {
      "goods_list": {
        "type": "nested",
        "properties": {
          "name":{
            "type":"text",
            "analyzer":"ik_max_word",
            "fields":{
              "name_sub_field_keyword":{
                "type":"keyword",
                "ignore_above": 256
              }
            }
          }
          ,"price":{
            "type":"text",
            "analyzer":"ik_max_word"
          }
        }
      }
    }
  }
}
查询嵌套结果
GET test_idx_nested/_search?pretty=true
{
  "query": {
    //指定是nested类型的数据的查询
    "nested": {
      //这个类型必须指定path就是表示从哪个field开始检索
      "path": "goods_list",
      "query": {
        //内部还得指定查询,这里使用bool,到这里就跟正常查询一样了
        "bool": {
          "must": [
            //第一个条件
            {
              "match": {
                "goods_list.name": "洗碗机"
              }
            }
            //第二个条件,如果第二个条件不符合是查不出结果的 
            ,{
              "match": {
                "goods_list.price": "4999"
              }
            }
          ]
        }
      }
    }
  }
}

多重嵌套例子

创建
PUT /test_multi_nested_area
{
  "mappings": {
    "properties": {
      "province": {
        "type": "nested",
        "properties": {
          "name": {
            "type": "text",
            "analyzer": "ik_max_word"
          },
          "cities": {
            "type": "nested",
            "properties": {
              "name": {
                "type": "text",
                "analyzer": "ik_max_word"
              },
              "district": {
                "type": "nested",
                "properties": {
                  "name": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
插入测试数据
PUT /test_multi_nested_area/_doc/1
{
  "province": {
    "name": "北京",
    "cities": [
      {
        "name": "北京市",
        "district": [
          {"name":"丰台区"},
          {"name":"海淀区"},
          {"name":"朝阳区"},
          {"name":"东城区"},
          {"name":"西城区"},
          {"name":"昌平区"}
          ]
      }
    ]
  }
}
PUT /test_multi_nested_area/_doc/2
{
  "province": {
    "name": "河南省",
    "cities": [
      {
        "name": "郑州市",
        "district": [
          {
            "name": "金水区"
          },
          {
            "name": "高新区"
          },
          {
            "name": "郑东新区"
          },
          {
            "name": "二七区"
          },
          {
            "name": "中原区"
          },
          {
            "name": "惠济区"
          }
        ]
      },
      {
        "name": "鹤壁市",
        "district": [
          {
            "name": "山城区"
          },
          {
            "name": "淇滨区"
          },
          {
            "name": "鹤山区"
          },
          {
            "name": "朝歌"
          },
          {
            "name": "浚县"
          }
        ]
      }
    ]
  }
}
PUT /test_multi_nested_area/_doc/3
{
  "province": {
    "name": "台湾省",
    "cities": [
      {
        "name": "台北市",
        "district": [
          {
            "name": "中正区"
          },
          {
            "name": "大同区"
          },
          {
            "name": "中山区"
          },
          {
            "name": "万华区"
          },
          {
            "name": "信义区"
          },
          {
            "name": "松山区"
          }
        ]
      },
      {
        "name": "高雄",
        "district": [
          {
            "name": "小港区"
          },
          {
            "name": "鼓山区"
          },
          {
            "name": "三民区"
          }
        ]
      }
    ]
  }
}
查询

city为包含北京市或者淇滨区的[省份]

GET /test_multi_ nested_area/_search
{
  "query": {
    "nested": {
      "path": "province",
      "query": {
        "nested": {
          "path": "province.cities",
          "query": {
            "bool": {
              "should": [
                {
                  "match": {
                    "province.cities.name": "北京市"
                  }
                },
                {
                  "nested": {
                    "path": "province.cities.district",
                    "query": {
                      "bool": {
                        "must": [
                          {
                            "match": {
                              "province.cities.district.name": "淇滨区"
                            }
                          }
                        ]
                      }
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}

fields设计目的

在 Elasticsearch 中,fields 是用于定义字段的子字段(sub-field)的部分。它的作用是为同一个字段提供不同的处理和索引选项。

常见的使用场景和解决的问题包括:

  1. 排序:使用子字段定义一个字段的关键字(keyword)类型,可以用于排序操作。关键字类型是不分析的,它存储原始的、未经分析的文本,并且可以精确匹配和排序。这对于需要对文本字段进行精确排序的场景非常有用,例如按字母顺序对名称进行排序。

  2. 聚合:使用子字段定义一个字段的关键字类型,可以在聚合操作中使用。聚合是 Elasticsearch 中强大的数据分析工具,它允许根据文档的字段值进行分组、计数、求和等操作。关键字类型可以在聚合操作中提供准确的、无需分析的文本匹配。

  3. 高亮显示:使用子字段定义一个字段的关键字类型,可以在搜索结果中进行高亮显示。高亮显示是一种突出显示搜索结果中匹配的文本的方式,它可以提高用户体验和搜索结果的可读性。关键字类型可以用于精确匹配并保留原始文本,从而在高亮显示中提供准确的结果。

  4. 多字段查询:使用子字段定义一个字段的不同类型,可以根据不同的查询需求进行优化。例如,可以为一个字段定义一个文本类型子字段和一个关键字类型子字段,分别用于全文搜索和精确匹配。这样可以根据查询类型选择合适的子字段进行查询,并获得更好的搜索结果。

通过使用 fields 定义子字段,您可以更细致地控制字段的处理和索引行为,以满足不同的查询需求,并在排序、聚合、高亮显示和多字段查询等方面提供更好的功能和性能。文章来源地址https://www.toymoban.com/news/detail-539157.html

到了这里,关于Elasticsearch 复杂类型 Nested的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ElasticSearch第五讲 ES nested嵌套文档与父子文档处理

    在ES中,处理实体之间的关系并不像关系型存储那样明显。在关系数据库中的黄金准则 - 数据规范化,在ES中并不适用。在处理关联关系,嵌套对象和父子关联关系中,我们会讨论几种可行方案的优点和缺点。 紧接着在为可扩展性而设计中,我们会讨论ES提供的一些用来快速灵

    2024年02月02日
    浏览(36)
  • Elasticsearch实战(二十四)---ES数据建模一对多模型Nested结构

    我们如何把Mysql的模型合理的在ES中去实现? 就需要你对要存储的数据足够的了解,及对应用场景足够的深入分析,才能建立一个合适的模型,便于你后期扩展 一对一 模型 一对多 模型 多对多 模型 上一篇,我们介绍了 一对多模型,采用Object对象存储的巨大缺陷,本篇文章,我们

    2024年02月14日
    浏览(36)
  • Elasticsearch 基于 array 结构 的nested类型的索引的聚合查询

    这几天在做es的聚合查询,对那种一对多的产品数据查询的时候遇到了一些问题,做一下记录 针对每个产品名称[ product_name ]进行分组,并对预算[ budget ]求和 产品名称 预算 电视机 4000 手机 851 相机 5000 扑克牌 2 es查询语句==简化版 es查询的结果==简化版 注意电视机的doc_count为

    2024年02月16日
    浏览(45)
  • Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?

    这是来自社区的一个真实企业场景问题。 https://elasticsearch.cn/question/13135 如下所示, 希望在查出的结果后, 对结果进行后处理,对tags列表,根据depth进行排序。 Elasticsearch 能支持的排序方式罗列如下: 包含但不限于: 基于特定字段的排序 基于Nested对象字段的排序 基于特定

    2024年02月02日
    浏览(42)
  • ElasticSearch第十四讲 ES有条件复杂查询

    模糊匹配 模糊匹配主要是针对文本类型的字段,文本类型的字段会对内容进行分词,对查询时,也会对搜索条件进行分词,然后通过倒排索引查找到匹配的数据,模糊匹配主要通过match等参数来实现 match : 通过match模糊匹配条件内容 prefix : 前缀匹配 regexp : 通过正则表达

    2024年02月03日
    浏览(35)
  • ES es Elasticsearch 十三 Java api 实现搜索 分页查询 复杂查询 过滤查询 ids查询 等

    目录 Java api 实现搜索 Pom.xml 建立链接 搜索全部记录 增加规则值查某些字段 搜索分页 全代码 Ids 搜索 搜索Match搜索 multi_match 搜索 多字段搜索 复杂查询 bool查询 filter  bool 复杂查询增加过滤器查询 复杂擦好像加排序 日志 思路 参考 api 写法 写Java代码 请求条件构建层次

    2024年02月04日
    浏览(42)
  • Elasticsearch(019):es常见的字段映射类型之数组类型(arrays)

    在Elasticsearch中,没有专用的array数据类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值都必须具有相同的数据类型。 这一点是区别于nested的,nested指的对象的集合。而arrays则是单一类型的数组集合而已。 此外,不需要专门的类型类定义数组类型

    2024年02月13日
    浏览(30)
  • Elasticsearch (ES) 搜索引擎: 数据类型、动态映射、多类型(子字段)

    原文链接:https://xiets.blog.csdn.net/article/details/132348634 版权声明:原创文章禁止转载 专栏目录:Elasticsearch 专栏(总目录) ES 映射字段的 数据类型 ,官网文档参考:Field data types。 下面是 ES 常用的一些基本数据类型。 字符串 类型: keyword :类型。 text :文本类型。

    2024年03月23日
    浏览(45)
  • Elasticsearch基础篇(六):es映射和常用的字段类型

    官方地址:Mapping 在 Elasticsearch 中,映射是索引的关键组成部分,它定义了文档的结构和字段。每个文档都包含一个或多个字段,而映射定义了这些字段的数据类型、如何分析文本、字段是否可搜索等信息。 映射的主要作用包括: 定义字段类型 :你可以指定字段是文本、数

    2024年02月04日
    浏览(72)
  • ElasticSearch第八讲 ES索引字段映射类型以及动态映射相关操作

    ES的映射:映射就是 Mapping,它用来定义一个文档以及文档所包含的字段该如何被存储和索引。所以,它其实有点类似于关系型数据库中表的定义。其中ES中映射可以分为动态映射和静态映射,静态映射就是提前创建好对应字段文档映射关系,如果插入的类型不对会出错,而动

    2024年02月10日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包