【问题标题】:how to return subgraph from gremlin that is in an easily consumable format for Java如何从 gremlin 返回以 Java 易于使用的格式的子图
【发布时间】:2017-05-09 08:05:03
【问题描述】:

当我尝试使用 Gremlin 进行一次遍历并一次从 DSE Graph 5.0 中带来很多东西时,我对非常简单的事情感到非常沮丧..

在我的简化案例中,我有:

  • 1 个具有特定 uuid 的实体
  • 实体可以有零个(参见可选)或多个类型
  • 我需要能够返回entitytypes

到目前为止,我所拥有的东西非常丑陋:(

List list = g.V().hasLabel("Entity").has("uuid","6708ec6d-4518-4159-9005-9e9d642f157e").as("entity")
        .optional(outE("IsOfType").as("types"))
        .select("entity", "types").toList();
List<Edge> typeEdges = new ArrayList<>();
Vertex entityV = null;
for (Object obj : list) {
    entityV = ((Vertex)((LinkedHashMap) obj).get("entity"));
    Edge typeEdge = ((Edge)((LinkedHashMap) obj).get("types"));
    typeEdges.add(typeEdge);
}

列表中的每一行都有实体和其中一种类型:/

我这样做是因为 Vertex 没有根据 DSE 5.0 Fluent API 中的遍历来填充 edges()。因此,要么我陷入了多次遍历,要么是一个巨大的可怕遍历,在 Java 对象中很难反序列化,或者我必须将 gremlin 查询作为字符串传递,但不会返回 Gremlin Vertex 对象,而是返回 DSE :(

在我不太简化的情况下,我想返回上述多个实体及其各自的类型,如何做到这一点?

最后,有什么好的方法可以为具有不同类型对象的子图的自定义对象映射生成可重用代码?

提前感谢您的帮助!

【问题讨论】:

  • 既然typeEdgesList,我可以假设一个实体可以有多种类型吗?
  • 我知道这听起来像是吹毛求疵,但需要澄清一下:DSE 5.0 fluent API 决定返回什么数据。这是决定行为的 TinkerPop 3 规范。
  • 好点亚历克斯!尽管正如我们在 jira 上讨论的那样,根据传递的查询类型(流利或字符串),返回的对象类型是 Gremlin 和 DSE 的。加上来自 DSE 的事务处理(使用next()toList() 等)而不是来自程序员的明确规定了特定的查询样式,因为在next()toList() 等之后,查询被发送到服务器并且edges() 未被填充在 Gremlin Vertex 对象和 Gremlin Edge 对象上没有填充 inVertex()/outVertex() Vertex 对象的属性
  • 我相信这些是 DataStax 团队做出的决定,而不是 TP3 标准,考虑到事情是如何在内部实现的,行为是什么,关于会话、事务以及对象是否将返回未填充或用于示例将被懒惰地评估。当然 API 和返回类型是由 TP3 规范强加的。 TitanDB 采用了不同的方法(由于某些原因更糟,对其他人更好)并且实现了不同风格的 Gremlin,即使 API 相同

标签: java datastax-enterprise gremlin datastax-enterprise-graph


【解决方案1】:

如果Entity:Type1:n 关系,那么您甚至不需要optional()

g.V().has("Entity","uuid","6708ec6d-4518-4159-9005-9e9d642f157e").
  project("entity","types").by().by(outE("IsOfType").fold())

结果的类型为List&lt;Map&lt;String, Object&gt;&gt;

更新

根据下面 cmets 中简短的 toList() 讨论,您可以通过以下方式处理遍历结果,而无需将整个内容存储在集合中:

g.V().has("Entity","uuid","6708ec6d-4518-4159-9005-9e9d642f157e")
        .project("entity","types").by().by(outE("IsOfType").fold())
        .forEachRemaining(m -> {
            final Vertex entityV = (Vertex) m.get("entity");
            final List<Edge> typeE = (List<Edge>) m.get("types");
            // whatever ...
        })

【讨论】:

  • 谢谢丹尼尔!您的意思是特定结果集中的 1/n 还是一般图表中的 1/n?我的意思是,即使在特定的结果集中,两个实体也可能共享相同的类型。多个实体及其类型如何,例如,如果我一次获取所有实体及其类型?
  • 结果集中的每一行都是一个Entity,然后是它的类型或类型。另一种方式(从类型到实体)无关紧要。简而言之,如果一个实体可以有多种类型,那么我们不需要更改任何内容。
  • toList() 对于这个特定的遍历肯定会返回一个List&lt;Map&lt;String, Object&gt;&gt;。如果不是这种情况,那么您要么修改了遍历,要么我们在 TP 版本之间存在差异。我怀疑是后者。无论如何,我知道如果无法从遍历中推断出正确的类型,您(应该)知道如何转换结果。
  • has("a","b","c")hasLabel("a").has("b","c") 的快捷方式。
  • 关于toList():我从来没有在我的答案中添加这个,因为我不知道其余代码将如何处理结果。可能是您实际上想使用toSet(),或者您根本不想使用集合,而是使用.forEachRemaining(...) 迭代结果集。
猜你喜欢
  • 2017-05-06
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
  • 1970-01-01
  • 2013-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多