掌握ElasticSearch(八):聚集、文档间的关系

news2024/11/5 19:54:59

文章目录

  • 一、聚集
    • 聚集类型
    • 示例
  • 二、文档间的关系
    • 1. 对象类型(Object Type)
    • 2. 嵌套文档(Nested Documents)
      • 定义嵌套字段
      • 索引嵌套文档
      • 查询嵌套文档
    • 3. 父子关系(Parent-Child Relationship)
      • 定义父子关系
      • 索引父文档和子文档
        • 索引父文档
        • 索引子文档
      • 查询父子关系
        • 查询父文档及其子文档
        • 查询子文档及其父文档
      • 更新父子关系
        • 更新父文档
        • 更新子文档
      • 删除父子关系
        • 删除父文档
        • 删除子文档
    • 4. 反规范化(Denormalization)
      • 示例
    • 5.性能对比

一、聚集

Elasticsearch 是一个基于 Lucene 的分布式搜索和分析引擎。它允许用户以近乎实时的方式存储、搜索和分析大量的数据。在 Elasticsearch 中,聚集(Aggregations)是一种强大的工具,用于执行复杂的汇总统计,如计数、平均值、最大值、最小值等。通过聚集,可以对数据进行深入分析,帮助我们更好地理解数据集。

聚集类型

Elasticsearch 支持多种类型的聚集,主要包括以下几类:

  1. 度量聚集(Metric Aggregations)

    • 这是最基本的聚集类型,用于计算数值字段的度量值。例如,avg(平均值)、sum(总和)、min(最小值)、max(最大值)、value_count(计数)、stats(统计数据)、extended_stats(扩展统计数据)等。
  2. 桶聚集(Bucket Aggregations)

    • 桶聚集将文档分成多个组或“桶”,每个桶代表一组满足特定条件的文档。常见的桶聚集包括:
      • terms:根据字段值分组。
      • histogram:根据数值字段创建直方图。
      • date_histogram:根据日期字段创建直方图。
      • range:根据数值或日期范围分组。
      • geo_distance:根据地理位置距离分组。
      • significant_terms:找出显著不同的术语。
  3. 管道聚集(Pipeline Aggregations)

    • 管道聚集用于处理其他聚集的结果。它们可以用于计算两个聚集结果之间的差异、百分比变化等。常用的管道聚集有 derivative(导数)、moving_avg(移动平均)、bucket_script(脚本化桶)、bucket_selector(桶选择器)等。
  4. 矩阵聚集(Matrix Aggregations)

    • 矩阵聚集用于多变量数据分析,能够计算数值字段之间的相关性和协方差等统计指标。

示例

假设我们有一个包含员工信息的数据集,我们可以使用聚集来找出不同部门的平均工资:

GET /employees/_search
{
  "size": 0,
  "aggs": {
    "by_department": {
      "terms": {
        "field": "department"
      },
      "aggs": {
        "average_salary": {
          "avg": {
            "field": "salary"
          }
        }
      }
    }
  }
}

在这个例子中,by_department 是一个 terms 桶聚集,它按照 department 字段的值将文档分组。然后,在每个部门的文档组中,average_salary 度量聚集计算了 salary 字段的平均值。

虽然聚集功能强大,但它们也可能消耗大量资源,特别是当处理大规模数据集时。因此,在设计查询时应该考虑到性能优化,比如减少返回的桶数量、使用合适的字段类型等。

二、文档间的关系

在 Elasticsearch 中,文档间的关系可以通过几种方式来实现,包括对象类型、嵌套文档、父子关系和反规范化。每种方法都有其适用场景和优缺点。

1. 对象类型(Object Type)

对象类型是最简单的文档内嵌方式,它允许在一个文档中嵌入另一个对象。这种方式适用于对象之间关系紧密且不需要独立索引的情况。

  • 示例:
{
  "name": "John Doe",
  "address": {
    "street": "123 Main St",
    "city": "Anytown",
    "state": "Anystate"
  }
}
  • 优点:

  • 简单易用,适合简单的嵌入关系。

  • 查询效率高,因为所有数据都在同一个文档中。

  • 缺点:

  • 如果嵌入的对象很大或者很复杂,会导致主文档变得臃肿。

  • 嵌入的对象不能独立更新,需要重新索引整个主文档。

2. 嵌套文档(Nested Documents)

嵌套文档(Nested Documents)是 Elasticsearch 中一种高级的数据建模方式,用于处理复杂的数据结构。嵌套文档可以在主文档中嵌入多个子文档,并且每个子文档都可以独立索引和查询。这种方式特别适用于需要对嵌入对象进行精确匹配和复杂查询的场景。

  • 嵌套文档的基本概念
  1. 嵌套字段:嵌套字段是一个特殊的字段类型,它允许我们将多个子文档嵌入到主文档中。每个子文档都可以有自己的字段和值。

  2. 独立索引:嵌套文档中的每个子文档都是独立索引的,这意味着我们可以对每个子文档进行独立的查询和过滤。

  3. 精确匹配:由于嵌套文档是独立索引的,可以对嵌套文档中的字段进行精确匹配,而不会受到其他嵌套文档的影响。

定义嵌套字段

在 Elasticsearch 中,我们需要在映射(mapping)中定义嵌套字段:

PUT /my-index
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "interests": {
        "type": "nested",
        "properties": {
          "name": { "type": "keyword" },
          "type": { "type": "keyword" }
        }
      }
    }
  }
}

在这个示例中,interests 是一个嵌套字段,它包含两个子字段:nametype

索引嵌套文档

当索引一个包含嵌套字段的文档时,Elasticsearch 会自动将嵌套字段中的每个子文档独立索引:

POST /my-index/_doc
{
  "name": "John Doe",
  "interests": [
    { "name": "Hiking", "type": "Outdoor" },
    { "name": "Reading", "type": "Indoor" }
  ]
}

查询嵌套文档

要查询嵌套文档,需要使用 nested 查询。以下是一个示例,查询所有兴趣为 “Hiking” 的文档:

GET /my-index/_search
{
  "query": {
    "nested": {
      "path": "interests",
      "query": {
        "bool": {
          "must": [
            { "match": { "interests.name": "Hiking" }}
          ]
        }
      }
    }
  }
}
  1. 性能:嵌套文档会增加索引和查询的复杂度,因为每个嵌套文档都需要独立索引。如果有大量的嵌套文档,可能会对性能产生影响。

  2. 内存占用:嵌套文档会占用更多的内存,因为每个嵌套文档都需要独立存储和索引。

  3. 更新复杂度:更新嵌套文档需要重新索引整个主文档,这可能会导致额外的开销。

3. 父子关系(Parent-Child Relationship)

在 Elasticsearch 中,父子关系(Parent-Child Relationship)是一种用于处理多级文档关系的方法。这种关系允许将一个文档(子文档)关联到另一个文档(父文档),并且每个子文档可以独立索引和查询。这种方法适用于需要保持文档间关系但又希望每个文档都能独立操作的场景。

  • 父子关系的基本概念
  1. 父文档(Parent Document):父文档是主要的文档,可以包含多个子文档。
  2. 子文档(Child Document):子文档是依赖于父文档的文档,每个子文档都关联到一个父文档。
  3. 关系类型(Join Field):为了建立父子关系,需要在文档中定义一个特殊的关系类型字段,称为 join field

定义父子关系

在 Elasticsearch 中,需要在索引映射(mapping)中定义关系类型字段:

PUT /my-index
{
  "mappings": {
    "properties": {
      "my_join_field": {
        "type": "join",
        "relations": {
          "question": "answer"
        }
      },
      "title": { "type": "text" },
      "content": { "type": "text" }
    }
  }
}

在这个示例中,my_join_field 是一个关系类型字段,定义了两种关系:questionanswerquestion 是父文档类型,answer 是子文档类型。

索引父文档和子文档

索引父文档
POST /my-index/_doc
{
  "title": "What is the capital of France?",
  "my_join_field": {
    "name": "question"
  }
}
索引子文档
POST /my-index/_doc?routing=1
{
  "content": "The capital of France is Paris.",
  "my_join_field": {
    "name": "answer",
    "parent": "1"
  }
}

在这个示例中,routing 参数指定了父文档的 ID,my_join_field 中的 parent 字段也指定了父文档的 ID。

查询父子关系

查询父文档及其子文档

要查询父文档及其子文档,可以使用 has_childhas_parent 查询。以下是一个示例,查询所有有答案的问题:

GET /my-index/_search
{
  "query": {
    "has_child": {
      "type": "answer",
      "query": {
        "match_all": {}
      }
    }
  }
}
查询子文档及其父文档

以下是一个示例,查询所有答案及其对应的问题:

GET /my-index/_search
{
  "query": {
    "has_parent": {
      "parent_type": "question",
      "query": {
        "match_all": {}
      }
    }
  }
}

更新父子关系

更新父子关系文档需要重新索引整个文档。可以使用 update API 来更新文档:

更新父文档
POST /my-index/_update/1
{
  "doc": {
    "title": "What is the capital of France? (Updated)"
  }
}
更新子文档
POST /my-index/_update/2?routing=1
{
  "doc": {
    "content": "The capital of France is Paris. (Updated)"
  }
}

删除父子关系

删除父子关系文档时,可以直接删除相应的文档。删除父文档会自动删除其所有子文档,但删除子文档不会影响父文档。

删除父文档
DELETE /my-index/_doc/1
删除子文档
DELETE /my-index/_doc/2?routing=1
  • 注意事项:
  1. 性能:父子关系查询可能比普通查询慢,因为需要跨文档进行关联。
  2. 内存占用:父子关系会占用更多的内存,因为每个文档都需要独立存储和索引。
  3. 路由:在索引和查询子文档时,必须指定父文档的 ID 作为路由参数,以确保父子文档在同一分片上。

4. 反规范化(Denormalization)

反规范化(Denormalization)是数据建模的一种技术,通过在文档中重复存储相关数据来提高查询性能。在 Elasticsearch 中,反规范化是一种常见的做法,尤其适用于读多写少的场景。通过减少查询时的文档关联和连接操作,反规范化可以显著提升查询速度。

  • 反规范化的概念:

在传统的关系型数据库中,数据通常是规范化存储的,即每个实体(表)只存储一次,通过外键来建立实体之间的关系。这种方式有助于保持数据的一致性和减少数据冗余,但在查询时需要进行多次表连接操作,这可能会导致性能瓶颈。

相比之下,反规范化通过在文档中重复存储相关数据来避免这些连接操作。虽然这样做会增加数据冗余,但可以显著提高查询性能,特别是在处理大规模数据集时。

  • 反规范化的应用场景:
  1. 读多写少:如果应用程序中读取操作远多于写入操作,反规范化可以显著提高读取性能。
  2. 实时分析:在需要实时分析和快速响应的场景中,反规范化可以减少查询延迟。
  3. 复杂查询:对于需要进行复杂聚合和过滤的查询,反规范化可以简化查询逻辑,提高查询效率。

示例

假设我们有一个电子商务系统,其中包含商品(Product)和订单(Order)两个实体。在关系型数据库中,这两个实体可能分别存储在不同的表中,并通过外键关联。在 Elasticsearch 中,可以通过反规范化将订单信息嵌入到商品文档中,或者将商品信息嵌入到订单文档中。

  • 规范化模型:
// 商品文档
{
  "product_id": 1,
  "name": "iPhone 12",
  "category": "Electronics"
}

// 订单文档
{
  "order_id": 101,
  "customer_name": "John Doe",
  "product_id": 1,
  "quantity": 2,
  "total_price": 1998
}
  • 反规范化模型:

(1)将订单信息嵌入到商品文档中

{
  "product_id": 1,
  "name": "iPhone 12",
  "category": "Electronics",
  "orders": [
    {
      "order_id": 101,
      "customer_name": "John Doe",
      "quantity": 2,
      "total_price": 1998
    }
  ]
}

(2)将商品信息嵌入到订单文档中

{
  "order_id": 101,
  "customer_name": "John Doe",
  "product": {
    "product_id": 1,
    "name": "iPhone 12",
    "category": "Electronics"
  },
  "quantity": 2,
  "total_price": 1998
}
  • 反规范化的优点:
  1. 查询性能:通过减少文档间的关联和连接操作,查询性能可以显著提高。
  2. 简化查询:反规范化可以简化查询逻辑,使得查询更加直观和高效。
  3. 实时分析:对于需要实时分析和快速响应的场景,反规范化可以减少查询延迟。
  • 反规范化的缺点:
  1. 数据冗余:反规范化会导致数据冗余,占用更多的存储空间。
  2. 更新复杂度:更新数据时需要同步更新多个文档,增加了数据维护的复杂度。
  3. 数据一致性:数据冗余可能导致数据不一致的风险,需要额外的机制来保证数据的一致性。
  • 实践建议:
  1. 选择合适的反规范化策略:根据具体的应用场景和需求,选择合适的反规范化策略。例如,如果订单信息频繁更新,可以考虑将商品信息嵌入到订单文档中,反之亦然。
  2. 使用版本控制:在更新数据时,使用版本控制机制来确保数据的一致性。
  3. 定期清理冗余数据:定期检查和清理冗余数据,以减少存储空间的占用。
  4. 监控和优化:持续监控系统的性能,根据实际情况进行优化调整。

5.性能对比

  • 对象类型嵌套文档 适用于简单的嵌入关系,查询性能高,但不适合复杂的数据结构。
  • 父子关系 适用于需要独立索引但又保持关联关系的场景,但查询性能较低。
  • 反规范化 适用于读多写少的场景,查询性能高,但数据冗余。

与关系型数据库相比,Elasticsearch 在处理大规模数据集时具有更高的查询性能,但牺牲了一定的数据一致性和更新复杂度。选择哪种方式取决于具体的应用场景和需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2233778.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

API网关 - JWT认证 ; 原理概述与具体实践样例

API网关主要提供的能力,就是协议转换,安全,限流等能力。 本文主要是分享 如何基于API网关实现 JWT 认证 。 包含了JWT认证的流程,原理,与具体的配置样例 API网关认证的重要性 在现代Web应用和微服务架构中&#x…

Excel:vba实现批量插入图片

实现的效果: 实现的代码: Sub InsertImageNamesAndPictures()Dim PicPath As StringDim PicName As StringDim PicFullPath As StringDim RowNum As IntegerDim Pic As ObjectDim Name As String 防止表格里面有脏数据Cells.Clear 遍历工作表中的每个图…

什么是 OpenTelemetry?

OpenTelemetry 定义 OpenTelemetry (OTel) 是一个开源可观测性框架,允许开发团队以单一、统一的格式生成、处理和传输遥测数据(telemetry data)。它由云原生计算基金会 (CNCF) 开发,旨在提供标准化协议和工具,用于收集…

电商美工必备神器:千鹿 AI 轻松解决场景图主图尺寸问题

前言 在电商领域,美工在做详情页设计时,常常会为图片尺寸问题而苦恼。而 AI 扩图在此刻就成为了美工们的得力助手。其中,场景图主图太小是一个让人颇为头疼的难题。千鹿 AI 作为一款强大的工具,能够一键将图片改成指定尺寸&#…

关于 PDF 抽取的吐槽

今天一下午写了8,9个 PDF 抽取的脚本。最后又回归最开始简单的模式了,要疯了,谁懂啊。 我是下午的工作是这样的(我是这么疯的) 最开始使用最简单的策略,先使用 PyPDF2.PdfReader(file) 读取文件,然后在每一页使用 pag…

无人机避障——(局部规划方法)DWA(动态窗口法)

传统的DWA算法更加倾向于车辆等差速无人车,旋翼无人机是全速的,全向的。 全局路径是通过A*算法生成的 局部路径规划效果: DWA算法效果: 过程图: 完整过程: PID算法效果: 过程图&#xff1a…

知识吾爱纯净版小程序系统 leibiao SQL注入漏洞复现(XVE-2024-30663)

0x01 产品简介 知识吾爱纯净版小程序系统是一款基于微信小程序平台开发的知识付费应用,旨在帮助用户快速建立自己的知识付费平台,实现支付变现和流量主收益。它提供了简洁明了的用户界面和良好的用户体验,同时注重用户隐私保护,确保用户信息的安全存储和传输。 0x02 漏洞…

基于web的便捷饭店点餐小程序的设计与实现(lw+演示+源码+运行)

摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对高校教师成果信息管理混乱,出错率高,信息安全…

全面解析:深度学习技术及其应用

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 全面解析:深度学习技术及其应用 全面解析:深度学习技术及其应用 全面解析:深度学习技术及其应…

项目实战使用gitee

1.创建本地仓库 2.进行提交到本地仓库 创建仓库后在idea中会显示图标,点击绿色的√进行快速提交 3.绑定远程仓库 4.番外篇-创建gitee仓库 注意不要勾选其他

【鸿蒙新闻】10月29日警用鸿蒙开发者大会在北京胜利召开,开启智慧应用新时代!

10月29日,在公安部科技信息化局、公安部装备财务局指导下,由公安部第一研究所主办,鼎桥通信技术有限公司、OpenHarmony生态委员会及公共安全专委会协办的警用鸿蒙开发者大会在北京胜利召开。会议以“拥抱警鸿创新生态 开启智慧应用新时代”为…

Spring Boot 3.3 【九】Redis 的五种数据结构深入浅出(String List Set Hash Zset)

如果觉得本文能够帮到您,请关注🌟、点赞👍、收藏📚,让这份美好延续下去! 一、Redis 数据结构简介 在现代应用开发中,高效的数据存储和管理是构建强大系统的关键。Redis 作为一种高性能的内存数…

命令行参数、环境变量、地址空间

命令行参数: int main(int argc, char *argv[ ]),main的参数可带可不带。argc参数通常代表后面的char *argv的元素个数有多少。 在linux中会把输入的字符串存到char *argv[ ]中,在数组的结尾为NULL。 命令行参数可以让同一个程序可以通过不同…

持续优化,构建更好地 auto git commit 体验

几个月前,受到一篇推文的启发 https://x.com/mtrainier2020/status/1802941902964277379 ,我突然想到可以借助 git alias 添加一些小命令,加速我的 git workflow 流程,于是我花了两个小时的时间进行工程封装,并发布了 …

C#-类:声明类、声明类对象

一:类的声明 class 类名 {//特征——成员变量//行为——成员方法//保护特征——成员属性//构造函数和析构函数//索引器//运算符重载//静态成员 }类名:帕斯卡 同一个语句块中的不同类 不能重名 二:声明类对象 2.1 类的声明 ≠ 类对象的声…

【学习enable_if模板, 学习unqiue_str 删除操作】

enable_if 是 C 标准库中的一个模板结构体,它用于条件编译和 SFINAE(Substitution Failure Is Not An Error)。enable_if 的主要作用是通过条件编译来控制模板的实例化,从而实现条件编译和 SFINAE。 1. enable_if 的基本用法如下…

AIGC产品经理高频面试题❗️看完的都拿高薪了

🤔️如果你正在考虑找AI产品经理相关的工作, 建议好好准备这些面试问题, 如果想要更加详细的回答可以直接询问海螺AI哦! 谁用了不说一句: AI真的太适合准备面试啦(🙀尖叫抛开 之后会分享更多岗位的面试题目, 以及如何用AI准备面试的tips哦! 大模型&A…

【VS+QT】联合开发踩坑记录

最新更新日期:2024/11/05 0. 写在前面 因为目前在做自动化产线集成软件开发相关的工作,需要用到QT,所以选择了VS联合开发,方便调试。学习QT的过程中也踩了很多坑,在此记录一下,提供给各位参考。 1. 环境配…

Windows下安装Maven并配置环境

在Windows下安装Maven、修改阿里云仓库、修改本地仓库路径,并为IntelliJ IDEA配置Maven,可以按照以下步骤进行操作: 1. 安装Maven 下载Maven: 访问 Apache Maven官网,下载最新版本的Maven二进制包(zip格式…

基于SpringBoot+微信小程序+协同过滤算法+二维码订单位置跟踪的农产品销售平台-新

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍: “农产品商城”小程序…