Azure CosmosDB上的Gremlin:如何投影相关顶点的属性?

Dej*_*vić 1 graph-databases gremlin azure-cosmosdb

我使用Microsoft.Azure.Graphs库连接到Cosmos数据库实例并查询图数据库.

我正在尝试优化我的Gremlin查询,以便只选择我只需要的那些属性.但是,我不知道如何选择从边和顶点中选择哪些属性.

假设我们从这个查询开始:

gremlin> g.V().hasLabel('user').
   project('user', 'edges', 'relatedVertices')
     .by()
     .by(bothE().fold())
     .by(both().fold())
Run Code Online (Sandbox Code Playgroud)

这将返回以下内容:

{
    "user": {
        "id": "<userId>",
        "type": "vertex",
        "label": "user",
        "properties": [
            // all vertex properties
        ]
    },
    "edges": [{
        "id": "<edgeId>",
        "type": "edge",
        "label": "<edgeName>",
        "inV": <relatedVertexId>,
        "inVLabel": "<relatedVertexLabel>",
        "outV": "<relatedVertexId>",
        "outVLabel": "<relatedVertexLabel>"
        "properties": [
            // edge properties, if any
        ]
    }],
    "relatedVertices": [{
        "id": "<vertexId>",
        "type": "vertex",
        "label": "<relatedVertexLabel>",
        "properties": [
            // all related vertex properties
        ]
    }]
}
Run Code Online (Sandbox Code Playgroud)

现在假设我们只从我们命名为"User"的根顶点获取一些属性:

gremlin> g.V().hasLabel('user').
   project('id', 'prop1', 'prop2', 'edges', 'relatedVertices')
     .by(id)
     .by('prop1')
     .by('prop2')
     .by(bothE().fold())
     .by(both().fold())
Run Code Online (Sandbox Code Playgroud)

这将为我们取得一些进展,并产生以下内容:

{
    "id": "<userId>",
    "prop1": "value1",
    "prop2": "value2",
    "edges": [{
        "id": "<edgeId>",
        "type": "edge",
        "label": "<edgeName>",
        "inV": <relatedVertexId>,
        "inVLabel": "<relatedVertexLabel>",
        "outV": "<relatedVertexId>",
        "outVLabel": "<relatedVertexLabel>"
        "properties": [
            // edge properties, if any
        ]
    }],
    "relatedVertices": [{
        "id": "<vertexId>",
        "type": "vertex",
        "label": "<relatedVertexLabel>",
        "properties": [
            // all related vertex properties
        ]
    }]
}
Run Code Online (Sandbox Code Playgroud)

现在可以做类似边和相关顶点的事情吗?说,有些东西:

gremlin> g.V().hasLabel('user').
   project('id', 'prop1', 'prop2', 'edges', 'relatedVertices')
     .by(id)
     .by('prop1')
     .by('prop2')
     .by(bothE().fold()
         .project('edgeId', 'edgeLabel', 'edgeInV', 'edgeOutV')
              .by(id)
              .by(label)
              .by(inV)
              .by(outV))
     .by(both().fold()
         .project('vertexId', 'someProp1', 'someProp2')
              .by(id)
              .by('someProp1')
              .by('someProp2'))
Run Code Online (Sandbox Code Playgroud)

我的目标是得到这样的输出:

{
    "id": "<userId>",
    "prop1": "value1",
    "prop2": "value2",
    "edges": [{
        "edgeId": "<edgeId>",
        "edgeLabel": "<edgeName>",
        "edgeInV": <relatedVertexId>,
        "edgeOutV": "<relatedVertexId>"
    }],
    "relatedVertices": [{
        "vertexId": "<vertexId>",
        "someProp1": "someValue1",
        "someProp2": "someValue2"
    }]
}
Run Code Online (Sandbox Code Playgroud)

ste*_*tte 6

你非常接近:

gremlin> g.V().hasLabel('person').
......1>   project('name','age','edges','relatedVertices').
......2>   by('name').
......3>   by('age').
......4>   by(bothE().
......5>      project('id','inV','outV').
......6>        by(id).
......7>        by(inV().id()).
......8>        by(outV().id()).
......9>      fold()).
.....10>   by(both().
.....11>      project('id','name').
.....12>        by(id).
.....13>        by('name').
.....14>      fold())
==>[name:marko,age:29,edges:[[id:9,inV:3,outV:1],[id:7,inV:2,outV:1],[id:8,inV:4,outV:1]],relatedVertices:[[id:3,name:lop],[id:2,name:vadas],[id:4,name:josh]]]
==>[name:vadas,age:27,edges:[[id:7,inV:2,outV:1]],relatedVertices:[[id:1,name:marko]]]
==>[name:josh,age:32,edges:[[id:10,inV:5,outV:4],[id:11,inV:3,outV:4],[id:8,inV:4,outV:1]],relatedVertices:[[id:5,name:ripple],[id:3,name:lop],[id:1,name:marko]]]
==>[name:peter,age:35,edges:[[id:12,inV:3,outV:6]],relatedVertices:[[id:3,name:lop]]]
Run Code Online (Sandbox Code Playgroud)

写Gremlin时应该考虑两点:

  1. 上一步的输出将输入到下一步的输入中,如果您没有清楚地看到特定步骤的结果,那么后面的步骤可能不会最终正确.在你的例子中,在第一个by()你添加project()之后,fold()它基本上是在说"嘿,Gremlin,List为我设计边缘." 但是在你的by()调制器中,project()对输入的处理不是List作为单个边缘而是作为单个边缘可能导致错误.在Java中,该错误是:"java.util.ArrayList无法强制转换为org.apache.tinkerpop.gremlin.structure.Element".像这样的错误是一个线索,在你的Gremlin某处你没有正确地遵循你的步骤的输出和输入.
  2. fold()获取遍历流中的所有元素并将它们转换为a List.那么你有很多物品的地方,现在你将拥有一个物体fold().要再次将它们作为流处理,您需要unfold()它们来分别对它们进行操作.在这种情况下,我们只需要fold()在project()为每个边/顶点执行子操作后将其移动到语句的末尾.但为什么我们需要fold()呢?答案是传递给by()调制器的遍历不会被它修改的步骤(在这种情况下project())完全迭代.该步骤仅调用next()以获取流中的第一个元素 - 这是设计的.因此,如果您希望处理整个a流,则by()必须将流缩减为单个对象.你可能做到这一点与fold(),但其他的例子包括sum(),count(),mean(),等.