【发布时间】:2017-10-04 00:37:16
【问题描述】:
我对图形数据库相当陌生,但是我已经广泛使用 SQL Server 和文档数据库(Lucene、DocumentDb 等)。我完全有可能以错误的方式处理此查询,因为我是图形数据库的新手。我正在尝试将一些逻辑转换为我们目前正在使用 SQL Server 的图形数据库(具体来说是通过 Gremlins 的 CosmosDB Graph)。更改的原因是这个问题集并不是 SQL Server 真正擅长的,因此我们的 SQL 查询(我们已经尽我们所能优化)真正开始成为我们应用程序的热点。
为了非常简要地概述我们的逻辑,我们运营了一个网上商店,允许管理员配置产品和用户具有多个级别的细粒度权限(如下所述)。根据这些权限,我们只向用户显示他们被允许查看的产品。
实体:
- 地区:一个地区由多个国家/地区组成
- 国家:一个国家有很多市场和很多地区
- 市场:市场是一个国家/地区的一组商店
- 商店:商店属于单一市场
用户拥有以下一组权限,每组可以包含多个值:
- 可以查看区域
- 可以查看国家
- 可以查看市场
- 可以查看商店
产品具有以下一组权限,每组可以包含多个值:
- 对区域可见
- 对国家可见
- 市场可见
- 对商店可见
尝试了几天后,这是我想出的查询。此查询确实有效并为给定用户返回了正确的产品,但是执行大约需要 25 秒。
g.V().has('user','username', 'john.doe').union(
__.out('can-view-region').out('contains-country').in('in-market').hasLabel('store'),
__.out('can-view-country').in('in-market').hasLabel('store'),
__.out('can-view-market').in('in-market').hasLabel('store'),
__.out('can-view-store')
).dedup().union(
__.out('in-market').in('contains-country').in('visible-to-region').hasLabel('product'),
__.out('in-market').in('visible-to-country').hasLabel('product'),
__.out('in-market').in('visible-to-market').hasLabel('product'),
__.in('visible-to-store').hasLabel('product')
).dedup()
有没有更好的方法来做到这一点?这个问题可能不是最适合图形数据库吗?
任何帮助将不胜感激!
谢谢, 克里斯
【问题讨论】:
-
遍历的哪一部分占用的时间最多?更具体地说,第一个
dedup()之前的遍历部分占用了 25 秒的多少? -
@stephenmallette 在第一次重复数据删除之前大约需要 30 毫秒,因此速度非常快。该重复数据删除的输出约为 600 个顶点。其余时间都在第二工会。第二个 union+dedup 的输出大约是 5000 个顶点。
-
1.这是针对分区图集合运行的吗?如果是,您将哪个属性用作分区键。 2. 您是在使用 Microsoft.Azure.Graphs .net SDK(如果是,是哪个版本)还是通过 gremlin 客户端使用 CosmosDB Graph 服务? 3. 你可以尝试删除联合并将其分成两个遍历并测试它们各自的持续时间吗?这将判断
union步骤是否存在问题。 -
@OliverTowers 1) 不,它没有分区。 2) 是的,我正在使用 Microsoft.Azure.Graphs SDK 的 v0.3.0-preview。 3)我针对单个商店运行了第二个联合,执行大约需要 350 毫秒。似乎它没有并行运行第二个联合(不确定是否应该这样做)。它运行第一个联合(30 毫秒),获取第一个联合的 600 个结果,并为每个结果运行第二个联合(350 毫秒)。所以 (30ms + (600 个结果 * 350ms)) = 21 秒。不过,我想不出更好的方法来编写此查询。
标签: gremlin azure-cosmosdb tinkerpop tinkerpop3