In Janusgraph, We can assign primitive type array into property of Vertex or Edge.
Sample code.
gremlin> arr = new int[2]
gremlin> arr[0] = 0
gremlin> arr[1] = 1
gremlin> g.E(1).property("prop1", arr)
Finding the property which has equal array members
gremlin> arr2 = new int[2]
gremlin> arr2[0] = 0
gremlin> arr2[1] = 1
gremlin> g.E().has("prop1", arr)
But how can I find them with member? (in this case, 0 or 1)
Thank you.
I didn't think you could search within arrays with JanusGraph with Gremlin directly as a property value. You'd have to match on the entire array value as you demonstrated. If you wanted to search the values independently of each other (0 or 1 as in your question) you would need to use multi-properties. Here is an example from a similar question with JanusGraph.
g.E().filter(values("prop1").unfold().is(0))
This query works. but I can't sure its performance is good enough.
Thank you
Related
I have a graph with a single vertex:
gremlin> g.V().valueMap(true)
==>{id=a, x=[foo], label=vertex}
The vertex can be found in the following query:
gremlin> g.V().has('x', 'foo')
==>v[a]
However, I would like to modify the above query with the additional match constraint: match the vertex if it does not have property "y", or if the vertex does have property "y" and the value for property "y" equals "bar".
I have constructed the following query.
g.V().has('x', 'foo').or(__.hasNot('y'), __.has('y', 'bar'))
The query returns no matching vertices. So, I think I am looking for something equivalent to "IFNULL()" in mysql.
Any advice is much appreciated!
Joel
There's nothing wrong with your or() filter, it should just work.
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV().property(id, 'a').property('x', 'foo').iterate()
gremlin> g.V().has('x', 'foo').or(__.hasNot('y'), __.has('y', 'bar'))
==>v[a]
Alternatively you can check that there's no y value that is not bar.
gremlin> g.V().has('x', 'foo').not(__.values('y').is(neq('bar')))
==>v[a]
However, double negations tend to be confusing, so I would just go with or().
I have a graph with two vertices having id(s) 'a' and 'b'.
gremlin> g.V()
==>v[b]
==>v[a]
There are two edges from 'a' to 'b'.
gremlin> g.E()
==>e[a6b4bead-c161-5a61-d232-abfa2bfad54e][a-LIKES->b]
==>e[10b4bead-a0fc-8d2c-d69f-26b3e9e4c5d8][a-KNOWS->b]
gremlin> g.E().valueMap(true)
==>{id=a6b4bead-c161-5a61-d232-abfa2bfad54e, semantics=social, label=LIKES}
==>{id=10b4bead-a0fc-8d2c-d69f-26b3e9e4c5d8, semantics=social, label=KNOWS}
My question: given an id for one of the edges, I would like to find all other edges with the same value for the property "semantics". For example, given a.LIKES.id, I would like to execute a query that will return a.KNOWS using the value a.LIKES.semantics.
I started with:
g.E('a6b4bead-c161-5a61-d232-abfa2bfad54e')
.property('semantics').as('semantics')...this is where I am stuck
Thanks,
Joel
where() in conjunction with a by() modulator will do the job:
g.E('a6b4bead-c161-5a61-d232-abfa2bfad54e').as('e').
outV().inE().
where(eq('e')).by('semantics'). // return edges with the same semantics property value
where(neq('e')) // ... except the one we started with
I'm sure this is straightforward, but I'm not sure how to do it. I have vertices, with a certain label, which have two integer properties. Let's call them integer1 and integer2. I simply want to query for all vertices where integer2 is greater than integer1.
I have tried the following:
g.V().hasLabel("myLabel").has("integer2", P.gt(values("integer1"))).toList();
but this results in an exception - understandably, as the the "values" method call results in a traversal step where as the predicate expects a number.
Exception in thread "main" java.lang.ClassCastException: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal cannot be cast to java.lang.Integer
at java.lang.Integer.compareTo(Integer.java:52)
at org.apache.tinkerpop.gremlin.process.traversal.Compare$3.test(Compare.java:92)
at org.apache.tinkerpop.gremlin.process.traversal.P.test(P.java:72)
at org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer.testValue(HasContainer.java:118)
at org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer.test(HasContainer.java:94)
at org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer.testAll(HasContainer.java:180)
at org.apache.tinkerpop.gremlin.tinkergraph.process.traversal.step.sideEffect.TinkerGraphStep.iteratorList(TinkerGraphStep.java:116)
at org.apache.tinkerpop.gremlin.tinkergraph.process.traversal.step.sideEffect.TinkerGraphStep.vertices(TinkerGraphStep.java:88)
at org.apache.tinkerpop.gremlin.tinkergraph.process.traversal.step.sideEffect.TinkerGraphStep.lambda$new$0(TinkerGraphStep.java:59)
at org.apache.tinkerpop.gremlin.tinkergraph.process.traversal.step.sideEffect.TinkerGraphStep$$Lambda$23/1123629720.get(Unknown Source)
...
Any help would be greatly appreciated. Thanks.
One way to do it would be with a where() clause. First, to demonstrate I modified the "modern" graph to include a "k" property with an integer value:
g = TinkerFactory.createModern().traversal()
g.V().hasLabel('person').property('k',30)
and then:
gremlin> g.V().hasLabel('person').as('a').
......1> where('a', gt('a')).by('age').by('k').
......2> valueMap('age','k')
==>[k:[30],age:[32]]
==>[k:[30],age:[35]]
I'm using Java to access Gremlin. I have the following lines of code for creating a path between two vertices in an already created graph:
//begin simple path finding
Vertex fromNode = g.V().has("name", "i2").next();
Vertex toNode = g.V().has("name", "state1").next();
ArrayList list = new ArrayList();
g.V(fromNode).repeat(both().simplePath()).until(is(toNode)).limit(1).path().fill(list);
However, at this point I"m stuck. I can print out the list using list.toString() and I get the vertices that (I believe) are on the path. However, I now want to get those vertices themselves, access and potentially mutate their data. For instance, it isn't enough to know that v[32] is on the path if I can't access the ID 32 itself.
I should mention that I'm a bit new to this so please let me know if I'm using outdated/incorrect practices.
You ended up with a list filled with Path objects. I think what you're looking for is the unfold() step (see the docs) so you can unroll/flatten out the elements in path to put into the list. Here's a Gremlin Console session showing it:
gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> g = graph.traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV("name", "i2").as("a").addV("name", "state1").addE("to").from("a").toList()
==>e[4][0-to->2]
gremlin> fromNode = g.V().has("name", "i2").next()
==>v[0]
gremlin> toNode = g.V().has("name", "state1").next()
==>v[2]
gremlin> l = new ArrayList()
gremlin> g.V(fromNode).repeat(both().simplePath()).until(is(toNode)).limit(1).path().fill(l)
==>[v[0],v[2]]
gremlin> l = []; g.V(fromNode).repeat(both().simplePath()).until(is(toNode)).limit(1).path().fill(l)
==>[v[0],v[2]]
gremlin> l = []; g.V(fromNode).repeat(both().simplePath()).until(is(toNode)).limit(1).path().unfold().fill(l)
==>v[0]
==>v[2]
gremlin> l[0].getClass()
==>class org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex
gremlin> l[0].property("name", "j3") // mutate the vertex's name
==>vp[name->i3]
gremlin> g.V(fromNode).valueMap(true).toList()
==>[id:0,name:[j3],label:vertex]
You should have access to these through list you're using on the fill step. The toString method won't print out the properties. If you just want to see those, you can call valueMap() instead of fill at the end of your traversal. If you'd like to iterate over all of the vertices and get the properties, you can use the properties method. If you want to get a specific property, you can use the property(key) method. The rest of what you'd need is in the API docs
Is there a way to return just a subset of all properties of a graph node with a Gremlin query?
I know you cand use the transform pipe to concatenate property values, but I'm more interested in obtaining structured results (like propertyName1 = value1, propertyName2 = value2).
Assuming you're using Gremlin-Groovy, I find using Groovy's each construct to be a useful way to create my own objects from Gremlin query results. For example:
nodes = []
g.V.each{ node ->
nodes += [ propertyName1 : node.value1, propertyName2 : node.value2 ]
}
Now you have a List of Map objects representing nodes returned from your query. It's possible this isn't the most efficient way but it is very flexible.
As of Gremlin 2.4.0, you can do:
gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.v(1).out.map('name')
==>{name=vadas}
==>{name=josh}
==>{name=lop}
gremlin> g.v(1).out.map('name','age')
==>{age=27, name=vadas}
==>{age=32, name=josh}
==>{age=null, name=lop}
It is possible doing this:
If data is:
gremlin> g.E.has('weight', T.gt, 0.5f).outV.age
==>32
==>29
Then the query to do is:
gremlin> g.E.has('weight', T.gt, 0.5f).outV.transform{[id:it.id,age:it.age]}
==>{id=4, age=32}
==>{id=1, age=29}
Have you looked at using Table??
Sample from : Gremlin Wiki
gremlin> t = new Table()
gremlin> g.v(1).out('knows').as('x').out('created').as('y').table(t){it.name}{it.name}
==>v[5]
==>v[3]
gremlin> t
==>[x:josh, y:ripple]
==>[x:josh, y:lop]