Graph—Elastic Stack 实战手册

Graph—Elastic Stack 实战手册

更多精彩内容,请下载阅读全本《Elastic Stack实战手册》


加入创作人行列,一起交流碰撞,参与技术圈年度盛事吧


创作人:杨丛聿
审稿人:朱荣鑫

图作为一种现实中广泛存在的结构,与我们的生活息息相关,如社交网络、交通网络等。如何抽象的描述这些结构,并对其进行分析,获取潜在价值是一个普遍存在的问题。

相比于我们熟悉的关系数据库的建模方式,从 Graph 的角度出发,可以让一些复杂问题和场景的处理变得简单,如行为分析、个性化推荐、知识图谱等。

通常来讲,对于图的研究,分为图存储和图计算分析两个场景,二者解决的问题不同,相应的技术栈也有一些差异。

图存储

更强调图结构的建模,以及解决诸如邻居、路径等查询问题。

图计算

则是从全局或子图的角度为出发点,经过大量计算,来发现更深层次的问题,其关注的技术点,更多的是资源调度,以及各类经典图分析算法的实现。

Elasticsearch 的 Graph 功能介于二者之间,其定位是对已有的结构化数据进行分析,从图的角度去审视已有数据,并发现潜在价值。

图通常是以 vertex 和 edge 的模型管理数据,Elasticsearch 也不例外,只是区别于图数据库的先建模后存储,Elasticsearch 中 Graph 的建模逻辑,是在查询中动态填入的,其底层实现逻辑是基于 Elasticsearch 的 terms 和 aggregations 相关功能。

相比于图数据库通常只提供基于 vertex 和 edge 的基础查询,Elasticsearch 由于本身在构建倒排索引时会统计词频,这使其在查询层面,兼具一定的分析能力。可见 Elasticsearch Graph 本身的定位并不是图结构数据的管理(如知识图谱),而是在已有的结构化数据中,以图的视角来发现一些问题。如库中已存在用户的听歌记录,则可以根据听众偏好,为其进行歌曲的推荐。

其他图数据库概览

由于 Elasticsearch 本身从逻辑上更接近图数据库,不管是 vertices + connections 的数据模型还是查询模式,本节先介绍下目前主流图数据库的类别和实现逻辑,具体细节不进行展开。

目前主流的图数据库,以属性图和 RDF 模型为主;

RDF 相对小众,仅有 DGraph 属于此范畴;

属性图是由节点、边、属性三者构成的有向图,相比于其他数据库,其关键特征之一是边(或连接)与顶点一同被视为模型的核心组件;

基于这些理念,一般属性图数据的结构可以归纳如下:

每个顶点(vertex)包括:

  • 唯一标识符
  • 一组出边
  • 一组入边

一组属性(键值对

每条边(edge)包括:

  • 唯一标识符

边的起点

  • 边的终点
  • 描述两个顶点间关系类型的标签

一组属性(键值对)

对于各类图数据库而言,数据建模的核心便是如何组织这些数据,从存储和索引的角度来看,目前主要分为自行实现和 Graph 层两种:

自行实现存储&索引

代表如 neo4j,其使用了免索引邻接,即每个节点都会维护其相邻节点的引用,免去了基于索引查找相邻节点的开销,这个设计理念在很多图数据库中都可以看到;

以 Graph 层的形式构建,使用外置 Nosql 存储和外置索引

代表 JanusGraph、HugeGraph,对于此类图数据库,Elasticsearch 便可作为其索引层存在。

除此以外,如何在分布式场景下,对存储和计算进行优化,是各类图数据库遇到的最大问题,针对诸如分布式场景下的分片、删除等问题,逐步诞生了 NebulaGraph、 Dgraph 等。

Elasticsearch 的实现方式

Elasticsearch 的 Graph 功能始于 5.5 版本,属于 X-pack 的扩展功能组,从 API 的路径 /_graph/explore 可以看出,其定位更倾向于是探索分析,即在已有的索引上通过聚合的方式进行分析。

常规的 graph 查询可以理解为,先进行两层嵌套的 terms 聚合,再将查询结果以 vertexs 和 connections 的数据模型进行返回。

在使用 Graph 功能时,有3个核心要素,分别是 vertices、connections、controls,前两者主要用于确定图查询中,前者通过哪些字段产生,后者用于控制一些查询细节。

如希望通过点击日志探查用户的搜索词和点击的产品间的关联,可通过如下查询

POST clicklogs/_graph/explore
{
  "query": {                  
    "match": {
      "query.raw": "midi"
    }
  },
  "vertices": [               
    {
      "field": "product"
    }
  ],
  "connections": {            
    "vertices": [
      {
        "field": "query.raw"
      }
    ]
  }
}

查询语句中

  • vertices 用于指定对哪些字段的内容感兴趣,后续会作为 target 节点处理,对应的字段必须是已索引的字段。
  • connections 用于指定希望哪些字段和 vetices 的内容进行关联,后续会作为 source 节点处理,connections 也支持使用 query 缩小关联内容的范围。

这个查询会以聚合的方式得到最终结果,会产生类似两层嵌套 aggs 的查询效果

"aggs": {
    "vertices": {
      "terms": {
        "field": "product"
      },
      "aggs": {
        "connections": {
          "terms": {
            "field": "query.raw"
          }
        }
      }
    }
  }

查询结果会返回 vertices 和 connections 两个数组,通过这两部分数据,即可构成一个有向图(方向是由 connections 中设定的 query.raw 指向 vertices 中设定的 product)。

为了能更直观的反映每个节点,和每条边的重要程度,vertices 和 connections 的元素中均会额外返回一个 weight,这点也是 Elasticsearch Graph 区别于其他图数据库查询的功能点之一。

"vertices": [ 
      {
         "field": "query.raw",
         "term": "midi cable",
         "weight": 0.08745858139552132,
         "depth": 1
      },
      {
         "field": "product",
         "term": "8567446",
         "weight": 0.13247784285434397,
         "depth": 0
      }
],
"connections": [ 
      {
         "source": 0,
         "target": 1,
         "weight": 0.04802242866755111,
         "doc_count": 13
      }
]

除了上述例子所举的常规查询模式外,Elasticsearch 的 Graph API 还可以通过 controls 控制采样规模和 weight 的计算:

use_significance(默认 false)

如设置为 true,第二层的聚合将会变为 Significant Terms,得到的 weight 会是通过前置和后置频率算出的,可用来发现一些有趣,或不寻常的节点或关系。

sample_size(默认100)

通过减少采样规模,可以有效提高检索效率

除此以外,Elasticsearch 还支持通过 Kibana 配置 Graph 相关的可视化页面,借此可以快速将上述查询得到的结果以图形化的方式进行展现。以下示例基于 7.10 操作:

  1. 在 Kibana 中选择 Graph 进入导航页面;
  2. 选取一个数据源,即库中已存在的索引;

Graph—Elastic Stack 实战手册

图1 Kibana 操作-选取数据源

  1. 添加字段并触发查询即可得到如下的图结构分析页面 (可变更颜色区分节点),上文提及的 weight 值将通过节点间连线的粗细体现。

Graph—Elastic Stack 实战手册

图2 Kibana 操作-以图的视角分析索引不同字段

总结

高可用和近实时的能力

Elasticsearch 的 Graph 功能通过 X-pack 提供,其优点是可以对库中已有的数据,快速进行分析,且具备可视化能力。其天然具备高可用和近实时的能力。

千万以及亿级的数据进行 Graph 分析

依托于已有的倒排索引和聚合功能,可以快速以 vertices 和 connections 的数据模型呈现结果。由于聚合本身需要消耗较大的内存和计算量,在使用时需要留意数据量级和系统资源,在资源允许的情况下,可以支持对千万以及亿级的数据进行 Graph 分析。

当然 Elasticsearch 的 Graph 也存在一定局限性,它本身定位是对已有索引进行分析,因此不适合需要建模管理图结构数据的场景,且无法对多跳的路径查询进行有效支持。

并且 Elasticsearch Graph 内部的处理逻辑,是通过对索引进行字段级的聚合,因此产生关系的上下游节点仅限于同一索引中的不同字段。

综上,如果你希望发现索引中不同字段的一些潜在价值,不妨使用 Elasticsearch Graph 功能来进行探索。

参考资料

  1. https://www.elastic.co/guide/en/elasticsearch/reference/master/graph-explore-api.html
  2. https://www.elastic.co/guide/en/kibana/current/graph-getting-started.html
  3. https://nebula-graph.io/posts/review-on-graph-databases/
上一篇:安装 Elasticsearch (本地及 Docker)-Elastic Stack 实战手册


下一篇:阿里云Elasticsearch 生态&技术峰会 云生态下的开源共生之路【视频】