如何使用Gremlin沿路径收集所有顶点和边的属性?

5
这是一个非常简单的查询:
g.V('customerId').out().path()

这的JSON输出为:
{  
   "requestId":"96b26c1d-d032-2004-d36e-c700bd6db2a2",
   "status":{  
      "message":"",
      "code":200,
      "attributes":{  
         "@type":"g:Map",
         "@value":[  

         ]
      }
   },
   "result":{  
      "data":{  
         "@type":"g:List",
         "@value":[  
            {  
               "@type":"g:Path",
               "@value":{  
                  "labels":{  
                     "@type":"g:List",
                     "@value":[  
                        {  
                           "@type":"g:Set",
                           "@value":[  

                           ]
                        },
                        {  
                           "@type":"g:Set",
                           "@value":[  

                           ]
                        }
                     ]
                  },
                  "objects":{  
                     "@type":"g:List",
                     "@value":[  
                        {  
                           "@type":"g:Vertex",
                           "@value":{  
                              "id":"customerId",
                              "label":"customer"
                           }
                        },
                        {  
                           "@type":"g:Vertex",
                           "@value":{  
                              "id":"e:customerIdemail@email.com",
                              "label":"email"
                           }
                        }
                     ]
                  }
               }
            }
         ]
      },
      "meta":{  
         "@type":"g:Map",
         "@value":[  

         ]
      }
   }
}

现在,客户节点还包含姓名和年龄属性。我想要了解的是如何(如果可能的话)简单地形成我的Gremlin查询,使其嵌套图中的顶点属性。请注意,当我只运行g.V("customerId")时,响应确实包含这些属性。

1个回答

16

在遍历过程中,您应该始终明确指定要返回的数据。即使对于像这样的简单事情:

g.V('customerId')

你确实应该更喜欢:

g.V('customerId').valueMap('name','age')

在 SQL 中,实际上并没有太大的区别,你可能不会这样做。

SELECT * FROM customer

但是相反地

SELECT name, age FROM customer

就您的问题而言,您只需指定要返回的数据,因此请使用by()修饰符来为path()设置路径:

g.V('customerId').
  out().
  path().
    by(valueMap('name','age'))

当然,这假设你的out()也是一个“客户”,如果不是,只需添加第二个by(),并指定所需的特定字段即可。 by()调制器以轮流方式应用。如果你想要更干净一些的JSON处理,可以像下面这样使用project()

g.V('customerId').
  out().
  path().
    by(project('name','age').
         by('name').
         by('age'))

由于这样会消除valueMap()嵌入的列表,而这些列表是为了正确计算多属性而添加的。

从TinkerPop 3.4.4开始,您还应该考虑elementMap()步骤,它包括图元素更多的结构。

gremlin> g.V().has('person','name','marko').elementMap()
==>[id:1,label:person,name:marko,age:29]
gremlin> g.V().has('person','name','marko').elementMap('name')
==>[id:1,label:person,name:marko]
gremlin> g.V().has('person','name','marko').properties('name').elementMap()
==>[id:0,key:name,value:marko]
gremlin> g.E(11).elementMap()
==>[id:11,label:created,IN:[id:3,label:software],OUT:[id:4,label:person],weight:0.4]

有没有办法将这些数据包含在 gList 中的顶点或边类型之内?你给我的查询添加会返回 g:Map s 中的所有内容。我们希望能够实现一些数据同质化,以便我们可以在输出中保持一致性,并且拥有一个 DRY JSON unmarshaler。 - Wendell Blatt
当返回数据时,应查看标准集合。这回到了我关于明确返回内容的观点。图元素没有“部分”概念(即仅返回具有某些属性的Vertex),并且正如您在查询中看到的那样,我们将“分离”该顶点,以便您获得的只是id/label。我们将该形式的顶点称为“引用”顶点,在未来,TinkerPop将为所有遍历返回此类顶点(在某些图实现和TinkerPop序列化程序中已经起作用)。 - stephen mallette
如果你想知道为什么我们认为“完整”的顶点是“不好的”,那么你必须考虑多属性。想象一下一个有一百万个属性的顶点,如果你在path()中意外地返回了它,那么这将是一个昂贵的序列化过程来返回该结果。 - stephen mallette
好的,很公平。我感谢你向我解释这个问题。我还有一个问题:如何在“project(...)”中添加顶点ID?我尝试添加一个参数“id”,但似乎没有起作用。根据我们的实现,将映射解组成顶点属性相当简单,但如果没有主键,我无法识别映射属性所指向的顶点。 - Wendell Blatt
如果T被静态导入,那么它只是by(T.id)或者简单地by(id) - stephen mallette

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接