ElasticSearch父子索引实战

关于父子索引

ES底层是Lucene,由于Lucene实际上是不支持嵌套类型的,所有文档都是以扁平的结构存储在Lucene中,ES对父子文档的支持,实际上也是采取了一种投机取巧的方式实现的.

父子文档均以独立的文档存入,然后添加关联关系,且父子文档必须在同一分片,由于父子类型文档并没有减少文档数量,而且增加了父子绑定关系,会导致查询效率低下,因此我们并不建议您在实际开发中使用父子类型.

ES本身更适合"大宽表"模式,不要带着传统关系型数据库那种思维方式去使用ES,我们完全可以通过把多张表中的字段和内容合并到一张表(一个索引)中,来完成期望功能,尽可能规避父子类型的使用,不仅效率高,功能也更强大。

建议

如果对文档的写多于读,那么建议你选择父子类型,如果文档读多于写, 那么请选择嵌套类型。

对比嵌套文档

父子文档在理解上来说,可以理解为一个关联查询,有些类似MySQL中的JOIN查询,通过某个字段关系来关联。

父子文档与嵌套文档主要的区别在于,父子文档的父对象和子对象都是独立的文档,而嵌套文档中都在同一个文档中存储。

父-子关系的主要优势有:

  • 更新父文档时,不会重新索引子文档。
  • 创建,修改或删除子文档时,不会影响父文档或其他子文档。这一点在这种场景下尤其有用:子文档数量较多,并且子文档创建和修改的频率高时。
  • 子文档可以作为搜索结果独立返回。

实战案例

本篇以博客文章和评论作为文档模型,演示文章和评论这个一对多的父子关系,增删改查如何操作。

假设数据如下:

json 复制代码
[
    {
        "title":"这是一篇博文",
        "content":"适当方式连接管理工具螺丝钉解放了送到房间里伺机待发..."
    },
    {
        "username":"Jack",
        "comment":"nice post, good job!",
        "date":"2023-09-04"
    },
    {
       "username":"王老五",
        "comment":"写得很一般啊",
        "date":"2023-08-04"
    },
    {
        "username":"技术我最牛",
        "comment":"仅次于我",
        "date":"2022-05-01"
    }
]

创建索引

创建blog索引,父文档与子文档分别用不同的字段来存储对应的数据,在创建索引文档的时需要指定父子文档的关系,即文章为parent,评论为child,创建索引语句如下:

json 复制代码
{
  "mappings": {
    "properties": {
      "date": {
        "type": "date"
      },
      "username": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      },
      "comment": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      },
      "content": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      },
      "title": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      },
      "relation": {
        "type": "join",
        "relations": {
          "parent": "child"
        }
      }
    }
  }
}

添加文档

  • 父文档
    POST /blog/_doc/1

如果不指定relation 会报错:

  • 子文档
    子文档的插入语法如下,注意routing是父文档的id,平时我们插入文档时routing的默认就是id。

POST /blog/_doc/1?routing=1

查询文档

父子查询方式,常用分为两种特殊情况:

  • 根据子文档查询父文档 has_parent
    例如我要查询王老五的留言:

POST /blog/_search

json 复制代码
{
  "query": {
    "has_child": {
      "type": "comment",
      "query": {
        "match": {
          "username": "王老五"
        }
      }
    }
  }
}
  • 根据父文档查询子文档 has_child
    例如我要查询文章内容包含"工具"的所有评论:

POST /blog/_search

聚合查询与嵌套文档类似,比较简单,这里在说明另外一种场景:祖辈和孙辈可以创建吗?比如本文中的留言如果它也有子文档,那么可以根据文章查询孙辈吗?答案是可以的,只需要在has_child里面在嵌套一层has_child查询即可。

相关推荐
小江的记录本19 小时前
【分布式】分布式核心组件——分布式锁:Redis/ZooKeeper/etcd 实现方案(附全方位对比表)、优缺点、Redlock、时钟回拨问题
java·网络·redis·分布式·后端·zookeeper·架构
好家伙VCC19 小时前
**发散创新:用Rust实现基于RAFT共识算法的轻量级分布式日志系统**在分布式系统中,**一致性协议**是保障数据可靠
java·分布式·python·rust·共识算法
南棱笑笑生20 小时前
20260420给万象奥科的开发板HD-RK3576-PI适配瑞芯微原厂的Buildroot时调通AP6256并实测网速109Mbits/sec
大数据·elasticsearch·搜索引擎·rockchip
晔子yy20 小时前
【JAVA探索之路】从头开始讲透、实现单例模式
java·开发语言·单例模式
Elastic 中国社区官方博客1 天前
Elasticsearch:使用 Agent Builder 的 A2A 实现 - 开发者的圣诞颂歌
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
chools1 天前
【AI超级智能体】快速搞懂工具调用Tool Calling 和 MCP协议
java·人工智能·学习·ai
李白你好1 天前
TongWeb EJB 反序列化生成工具(Java-Chain 插件)
java·安全
历程里程碑1 天前
2. Git版本回退全攻略:轻松掌握代码时光机
大数据·c++·git·elasticsearch·搜索引擎·github·全文检索
U盘失踪了1 天前
Java 的 JAR 是什么?
java·jar
今天又在写代码1 天前
java-v2
java·开发语言