2015-12-02 19 views
5

So che questo è stato chiesto più volte ma non ho trovato alcun riferimento per quanto riguarda l'ultima versione di Tinkerpop (3.1), con molte nuove utili funzioni che possiamo usare in i nostri attraversamenti.Il modo migliore per trovare un percorso più breve tra due nodi in Tinkerpop 3.1

Diciamo che devo trovare a il percorso più breve tra i nodi 3 e 4. È questo suono trasversale?

g.V(3).repeat(out()).until(id().is(4).and().simplePath()).path().limit(1) 

Qui sto supponendo che quando sto loop una ricerca BFS viene eseguita (in tal modo, il primo risultato è il percorso più breve) come it seems that this was the case with the loop() function.

Inoltre, esiste un modo per includere una variabile associata in precedenza (utilizzando un passaggio as) nel passaggio until? Più precisamente, sto cercando di selezionare due nodi durante l'attraversamento, e poi trovare il percorso più breve tra di loro, per esempio,

g.V().match(
__as('e0').out('Feedbacks').as('e1'), 
__as('e0').repeat(out('Meets')).until(<I reach e1>).path().<get_length>.as('len') 
).select('e0', 'e1', 'len') 

Infine, come si può vedere dal attraversamento precedente, non è chiaro a io come posso ottenere la lunghezza del percorso più breve. Utilizzando qualcosa come

g.V(3).repeat(out()).until(id().is(4).and().simplePath()).path().size() 

restituisce la dimensione del risultato (numero di righe restituite), mentre

g.V(3).repeat(out()).until(id().is(4).and().simplePath()).path().by(__size()) 

restituisce un errore.

Ecco il grafico con cui sto sperimentando, se qualcuno vuole giocare un po '.

graph = TinkerGraph.open() 
e0 = graph.addVertex(T.id, 0, label, "User", "name", "e0") 
e1 = graph.addVertex(T.id, 1, label, "User", "name", "e1") 
e2 = graph.addVertex(T.id, 2, label, "User", "name", "e2") 
e3 = graph.addVertex(T.id, 3, label, "User", "name", "e3") 
e4 = graph.addVertex(T.id, 4, label, "User", "name", "e4") 
e0.addEdge("Feedbacks", e2) 
e0.addEdge("Meets", e1) 
e2.addEdge("Feedbacks", e4) 
e2.addEdge("Meets", e4) 
e3.addEdge("Feedbacks", e0) 
e3.addEdge("Meets", e2) 
e4.addEdge("Feedbacks", e0) 
g = graph.traversal() 

risposta

8

C'è una variante leggermente più corta per la query di percorso più breve:

g.V(3).repeat(out().simplePath()).until(hasId(4)).path().limit(1) 

La tua ipotesi, che il primo percorso è sempre il percorso più breve, è corretto. Per ottenere le lunghezze del percorso, è possibile utilizzare count(local):

g.V(3).repeat(out().simplePath()).until(hasId(4)).path().count(local) 

UPDATE

quanto riguarda la tua domanda aggiornato, questo dovrebbe risolvere il problema:

g.V().as("e0").out("Feedbacks").as("e1").select("e0"). 
     repeat(out("Meets")).until(where(eq("e1"))).path(). 
     map(union(count(local), constant(-2)).sum()).as("len"). 
     select("e0","e1","len") 

sottraggo 2 dal lunghezza complessiva del percorso, perché penso che ti interessi solo la lunghezza del percorso attraversato dal blocco repeat() e lo out().select() all'inizio non dovrebbe essere incluso. Se questo non è il caso, puoi semplicemente sostituire la 3a riga con count(local).as("len")..

+0

Grazie a @Daniel Kuppitz. Mentre scrivevi la tua risposta ho modificato la domanda. Avrai un po 'di tempo per controllare la nuova richiesta, cioè come faccio a fare riferimento a un nodo precedentemente alterato nel passaggio 'until()'? – Alberto

+0

Grazie ancora, Daniel – Alberto

+0

Scusa per il disturbo ancora una volta ma ... Sto cercando ora di unire i risultati delle due domande calcolando la lunghezza del percorso 'Meets' * non orientato * ('both ('Meets')') più breve collegare due vertici collegati da un bordo Feedback.Non è così banale dato che non posso usare 'simplePath()' all'interno di 'repeat()' a causa dei pattern 'as ('e0')' -'select ('e0') 'e non posso selezionare il primo percorso con un 'limite (1)' dopo 'until()' poiché altrimenti perdo le soluzioni. Hai qualche idea su come affrontarlo? – Alberto