2017-07-16 4 views
0

Compte tenu des données d'exemple suivantes, je voudrais construire une requête Gremlin qui retourne le réseau d'Alice de connexions rubis, 3 niveaux de profondeur:requête Gremlin à récupérer récursivement nœuds en fonction des propriétés de bord

Vertex: Alice 
Vertex: Bobby 
Vertex: Cindy 
Vertex: David 
Vertex: Eliza 

Edge: [Alice] -> [Rates(tag:ruby,value:0.9)] -> [Bobby] 
Edge: [Bobby] -> [Rates(tag:ruby,value:0.8)] -> [Cindy] 
Edge: [Cindy] -> [Rates(tag:ruby,value:0.7)] -> [David] 
Edge: [David] -> [Rates(tag:ruby,value:0.6)] -> [Eliza] # ignored, level 4 
Edge: [Alice] -> [Rates(tag:java,value:0.9)] -> [Eliza] # ignored, not ruby 

Ainsi, le retour les données doivent être quelque chose comme:

Bobby: [0.9] 
Cindy: [0.9, 0.8] 
David: [0.9, 0.8, 0.7] 

Où chaque ID de sommet est retourné, avec un tableau du chemin des valeurs d'évaluation. Je travaille dans la version actuelle de JanusGraph (Gremlin 3). Je suis assez nouveau à Gremlin; J'ai été curieux sur quelques recettes qui ont des choses en commun avec ma requête désirée, mais je ne vois toujours pas comment y arriver ...

Merci beaucoup pour toute aide ou conseil que vous pouvez offrir.

Répondre

2

Lorsque vous posez des questions Gremlin, il est toujours utile de ceux qui essaient de répondre si vous fournissez un graphique d'échantillon qui peut être facilement couper et coller dans la console Gremlin comme ceci:

graph = TinkerGraph.open() 
g = graph.traversal() 
g.addV().property('name','alice').as('a'). 
    addV().property('name','bobby').as('b'). 
    addV().property('name','cindy').as('c'). 
    addV().property('name','david').as('d'). 
    addV().property('name','eliza').as('e'). 
    addE('rates').property('tag','ruby').property('value',0.9).from('a').to('b'). 
    addE('rates').property('tag','ruby').property('value',0.8).from('b').to('c'). 
    addE('rates').property('tag','ruby').property('value',0.7).from('c').to('d'). 
    addE('rates').property('tag','ruby').property('value',0.6).from('d').to('e'). 
    addE('rates').property('tag','java').property('value',0.9).from('a').to('e').iterate() 

En utilisant ce graphique, je suis venu avec cette approche pour obtenir le résultat que vous désirez:

gremlin> g.V().has('name','alice'). 
......1> repeat(outE().has('tag','ruby').inV()). 
......2>  times(3). 
......3>  emit(). 
......4> group(). 
......5>  by('name'). 
......6>  by(path(). 
......7>  unfold(). 
......8>  has('value'). 
......9>  values('value'). 
.....10>  fold()) 
==>[bobby:[0.9],cindy:[0.9,0.8],david:[0.9,0.8,0.7]] 

Faisant suite par la ligne 3 avec le emit() est probablement assez explicite - trouver « alice », puis traverser out() à plusieurs reprises à une profondeur de 3 et émette chaque sommet découvert en cours de route. Que vous obtient les sommets que vous aimez:

gremlin> g.V().has('name','alice'). 
......1> repeat(outE().has('tag','ruby').inV()). 
......2>  times(3). 
......3>  emit() 
==>v[2] 
==>v[4] 
==>v[6] 

La partie plus compliquée vient après où vous êtes préoccupé par la récupération des informations de chemin pour chaque sorte que vous pouvez saisir les propriétés « valeur » le long de chaque bord « taux » . J'ai choisi d'utiliser group afin que je puisse facilement obtenir la structure Map que vous vouliez. Évidemment, si "bobby" apparaissait deux fois dans l'arbre, vous obtiendriez deux listes d'évaluations pour son entrée Map.

Si vous choisissez ce qui se passe dans group() vous pouvez voir qu'il est modulé par deux options by(). Le premier correspond à la clé dans le Map (évidemment, je suppose l'unicité sur "nom"). La seconde extrait le chemin du traversier actuel (le vertex de la personne). Avant d'aller prendre de plus un oeil à ce que la sortie ressemble avec juste le path():

gremlin> g.V().has('name','alice'). 
......1> repeat(outE().has('tag','ruby').inV()). 
......2>  times(3). 
......3>  emit(). 
......4> group(). 
......5>  by('name'). 
......6>  by(path()).next() 
==>bobby=[v[0], e[10][0-rates->2], v[2]] 
==>cindy=[v[0], e[10][0-rates->2], v[2], e[11][2-rates->4], v[4]] 
==>david=[v[0], e[10][0-rates->2], v[2], e[11][2-rates->4], v[4], e[12][4-rates->6], v[6]] 

Les étapes qui suivent path() manipuler cette voie dans la forme que vous voulez. il déroule chaque chemin puis filtre les bords en recherchant la propriété de bord "valeur", puis extrait cela et replie ensuite les valeurs dans une liste pour chaque valeur de la carte.

+0

Merci Stephen! Grande solution, avec une bonne explication. +100. –