当前位置: 首页 > 工具软件 > ElasticQuery > 使用案例 >

elasticsearch通过顶部多索引,实现联合查询

宇文飞翮
2023-12-01

一、前言

      之前试了下多索引查询,就是索引以数组的方式进行查询,发现这种方式是可以的。但是如果两个索引的名字,字段都不相同,可以实现类似于mysql的那种join效果吗,试试吧

elasticsearch的多索引联合查询以及范围日期查询示例

背景:使用es-php + es7.0

二、正文

1、首先索引部分还是以数组的形式

 'index' => ['zeusa.evony.com.accesslog-2019.03.28','zeusa.evony.com.accesslog-2019.03.29','users'],

2、进行普通查询

这一步发现了问题,就是如果要根据条件查询的话,那么多个索引之间必须有相同的条件字段才行,总结就是:
(1)、写法就是用数组的方式
(2)、注意type必须保持一致,不然会查不到
(3)、如果有条件,那么条件字段要保证每个索引中都有
(4)、查询出来的代码如下:

   [89]=>
      array(5) {
        ["_index"]=>
        string(5) "user1"
        ["_type"]=>
        string(3) "doc"
        ["_id"]=>
        string(20) "6CgEWGoBSw5ta76v3QnC"
        ["_score"]=>
        float(1)
        ["_source"]=>
        array(2) {
          ["@timestamp"]=>
          string(20) "2019-03-28T11:23:52Z"
          ["user_id"]=>
          int(299)
        }
      }
      [90]=>
      array(5) {
        ["_index"]=>
        string(36) "accesslog-2019.03.28"
        ["_type"]=>
        string(3) "doc"
        ["_id"]=>
        string(20) "3yEKxGkB18T84ql3g4oq"
        ["_score"]=>
        float(1)
        ["_source"]=>
        array(1) {
          ["@timestamp"]=>
          string(24) "2019-03-28T11:23:36.020Z"
        }
      }

3、优缺点

      可以看出来是两个索引下的数据,查出来之后是分散的数组。对于这种查询方式,最佳的用法是不同索引的结构完全相同,比如日志索引access_20190426access_20190427,这种结构相同的情况下,进行多索引联合查询是很合适的。

优点:

1、 对结构相同或者大部分字段相同的索引,可以使用这种方式进行多索引联合查询
2、 直接查询出来的就是数组,根据索引名处理下数组即可。还可以直接在查询出来的基础上进行聚合操作

缺点:

1、 如果索引的字段不同,就比如这里的user1和accesslog-2019.03.28,查询结果是出来了,但是如果要进行聚合操作,那么只能各自聚合各自的字段,不能进行子聚合。
2、 查询条件必须同时符合多个索引,但在业务层面,比如mysql的联表查询中,并不是要求每个表都必须遵循相同的查询条件的,可能只是a.id=b.id的关联关系。

三、如果要实现类似于mysql的联合查询

      首先,我们都知道,mysql做联合查询,表的字段都是有关联的,那么使用上面这种方式肯定是不行的,或者局限性很大。不可能让关联的索引保持字段都一致,业务上也说不过去。

1、网上的方案

网上的方案一般分为四种,这里参考: https://blog.csdn.net/laoyang360/article/details/79774481
(1)、应用端关联
(2)、宽表冗余存储(Data denormalization)
(3)、嵌套文档(Nested)存储
(4)、父子文档存储

      如果数据量不是很大的话,使用客户端join,也就是在业务层面查询两次也能实现类似于join的操作。如果数据量适中,多个索引之间联系紧密,比如博客和评论的关系,那么是可以考虑Nested&Join方式的,只是比较影响性能。nested 类型检索使得检索效率慢几倍,父子Join 类型检索会使得检索效率慢几百倍。

      如果你多索引是类似于博客表和用户表关联,关系不是很紧密且数据量很大的话,最好是采用宽表的方式。如果业务端对查询性能要求很高的话,还是建议使用宽表化处理的方式,这样也可以比较好地应对聚合的需求。在索引阶段需要做join处理,查询阶段可能需要做去重处理,分页方式可能也得权衡考虑下。

2、其次

      我们要知道,ES和大多数的nosql相似,想要处理mysql这种关联关系还是有些强人所难了。最好是在设计阶段就尽量设计成扁平化的文档模型,用拼接json的方式去处理数据,而不是还按照传统关系型数据库的思维去使用ES。性能和关联关系不可兼得,ES既然选择了性能,那就别嫌弃它处理关联不方便吧。

      博主的需求是分析日志于用户之间的关系,最终选用的方案是宽表模式,也就是咱们常说的数据冗余。毕竟数据量挺大的,采用其他方案都很影响效率。这个大家仁者见仁智者见智了,总之要改变自己的思维,关联起来太难了!

end

 类似资料: