diff --git a/query/gremlin/build_iterator.go b/query/gremlin/build_iterator.go index e49c2d4..1fd3b40 100644 --- a/query/gremlin/build_iterator.go +++ b/query/gremlin/build_iterator.go @@ -139,6 +139,16 @@ func buildInOutIterator(obj *otto.Object, qs graph.QuadStore, base graph.Iterato return iterator.NewHasA(qs, and, out) } +func buildInOutPredicateIterator(obj *otto.Object, qs graph.QuadStore, base graph.Iterator, isReverse bool) graph.Iterator { + dir := quad.Subject + if isReverse { + dir = quad.Object + } + lto := iterator.NewLinksTo(qs, base, dir) + hasa := iterator.NewHasA(qs, lto, quad.Predicate) + return iterator.NewUnique(hasa) +} + func buildIteratorTreeHelper(obj *otto.Object, qs graph.QuadStore, base graph.Iterator) graph.Iterator { // TODO: Better error handling var ( @@ -315,6 +325,10 @@ func buildIteratorTreeHelper(obj *otto.Object, qs graph.QuadStore, base graph.It and.AddSubIterator(subIt) and.AddSubIterator(notIt) it = and + case "in_predicates": + it = buildInOutPredicateIterator(obj, qs, subIt, true) + case "out_predicates": + it = buildInOutPredicateIterator(obj, qs, subIt, false) } if it == nil { panic("Iterator building does not catch the output iterator in some case.") diff --git a/query/gremlin/gremlin_test.go b/query/gremlin/gremlin_test.go index 52269b7..5c86b8f 100644 --- a/query/gremlin/gremlin_test.go +++ b/query/gremlin/gremlin_test.go @@ -250,6 +250,27 @@ var testQueries = []struct { `, expect: []string{"bob", "greg"}, }, + { + message: "list all bob's incoming predicates", + query: ` + g.V("bob").InPredicates().All() + `, + expect: []string{"follows"}, + }, + { + message: "list all in predicates", + query: ` + g.V().InPredicates().All() + `, + expect: []string{"follows", "status"}, + }, + { + message: "list all out predicates", + query: ` + g.V().OutPredicates().All() + `, + expect: []string{"follows", "status"}, + }, } func runQueryGetTag(g []quad.Quad, query string, tag string) []string { diff --git a/query/gremlin/traversals.go b/query/gremlin/traversals.go index 1576fc1..8eee050 100644 --- a/query/gremlin/traversals.go +++ b/query/gremlin/traversals.go @@ -40,6 +40,8 @@ func (wk *worker) embedTraversals(env *otto.Otto, obj *otto.Object) { obj.Set("SaveR", wk.gremlinFunc("saver", obj, env)) obj.Set("Except", wk.gremlinFunc("except", obj, env)) obj.Set("Difference", wk.gremlinFunc("except", obj, env)) + obj.Set("InPredicates", wk.gremlinFunc("in_predicates", obj, env)) + obj.Set("OutPredicates", wk.gremlinFunc("out_predicates", obj, env)) } func (wk *worker) gremlinFunc(kind string, prev *otto.Object, env *otto.Otto) func(otto.FunctionCall) otto.Value {