I am new to OrientDB and have these questions:
- Is there any more efficient way to get the relationships for a given entity than this method:
Iterable<Edge> vet1 = first_vertex.getEdges(Direction.valueOf("BOTH"));
for (Edge edge : vet1)
System.out.println(edge);
Should I parse the result edge e.g., [#9:526597-is_a->#9:8151] by myself to get for example this result: A is_a -> B ?
I should directly get the vertex names (also relationship type and direction) instead of getting only ids and then search for vertex names.
I have a solution but maybe there is faster than it is:
System.out.println(edge.getVertex(Direction.valueOf("OUT")).getProperty("name").toString() + edge.getLabel() + edge.getVertex(Direction.valueOf("IN")).getProperty("name").toString());
Thanks a lot
You can use
Iterable<Vertex> vet1=first_vertex.getVertices(Direction.BOTH, null);
for (Vertex v : vet1)
System.out.println(v);
Related
I am using a Github example to generate a graph (https://github.com/Azure-Samples/azure-cosmos-db-graph-java-getting-started). And now I want to query it and hold a vertex instance in my hand to traverse further depending on further inputs from the user in a knowledge graph.
Submitting this gremlin query: g.V().hasLabel('schedule').inE().outV().hasLabel('url').as('a').dedup()
.where(and(out().hasLabel('schedule').has('name','3'),out()
.hasLabel('states').has('name', 'federal'))).select('a')
// Submitting remote query to the server.
ResultSet results = client.submit(query);
CompletableFuture<List<Result>> completableFutureResults = results.all();
List<Result> resultList = completableFutureResults.get();
for (Result result : resultList) {
System.out.println("My vertex--"+result.getVertex());
System.out.println("\nQuery result:");
System.out.println("resultssssss-"+result.toString());
}
How can I do that as right now I am getting a class cast exception as mentioned below:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to org.apache.tinkerpop.gremlin.structure.Vertex
at org.apache.tinkerpop.gremlin.driver.Result.getVertex(Result.java:131)
at GetStarted.Dynamic.main(Dynamic.java:155)
The select('a') seems redundant to me - I think that can be removed. It is selecting an output that is already the current output of where() which is already that vertex at "a" which means your traversal should be:
g.V().hasLabel('schedule').
in().hasLabel('url').
dedup().
where(and(out().hasLabel('schedule').has('name','3'),
out().hasLabel('states').has('name', 'federal')))
I guess a further optimization would be to do the out() before the and() so you only traverse those edges once:
g.V().hasLabel('schedule').
in().hasLabel('url').
dedup().
where(out().and(has('schedule','name','3'),
has('states', 'name', 'federal')))
Now...that returns a Vertex, however, what you had should have also returned a Vertex. At least according to TinkerPop specifications, when doing a select() on a single label you should get back a single object. However, if you do multiple labels then you would get a Map. You can see this demonstrated with TinkerGraph here:
gremlin> g.V().hasLabel('person').as('a').out().as('b').select('a')
==>v[1]
==>v[1]
==>v[1]
==>v[4]
==>v[4]
==>v[6]
gremlin> g.V().hasLabel('person').as('a').out().as('b').select('a','b')
==>[a:v[1],b:v[3]]
==>[a:v[1],b:v[2]]
==>[a:v[1],b:v[4]]
==>[a:v[4],b:v[5]]
==>[a:v[4],b:v[3]]
==>[a:v[6],b:v[3]]
It makes me wonder if CosmosDB has that little nuance covered properly - if not, then that's technically a "bug".
I wanna to find all node and edge properties in graph. How can I list node (or edge) properties that exist in graph?
for example if nodes has 3 non-reserved properties such as NAME, education, gender. I wanna a methods like
g.V().schema().toList();
// result: [ID, LABEL, NAME, GENDER, EDUCATION]
Gremlin itself has no notion of schema. This was a deliberate design choice as the capabilities and behavior around schema APIs is quite different from one graph system implementation to the next and forming an appropriate abstraction in Apache TinkerPop for that is quite difficult. In this way it is quite akin to TinkerPop 2.x's attempt to build a general index API, which ended up being too generic to be useful to anyone and had there been more complexity added, more that what was required for most cases. In the end, like indexing APIs, ideas for generalizing schema were left out for TinkerPop 3.x.
If you use a graph that allows for schema definition like JanusGraph or DSE Graph you should simply use the underlying Schema API of that graph system to get all of your schema values. If you aren't using that type of graph then you will need to do something along the lines of what has been offered in the other answers thus far and iterate through all of the vertices (or edges) and get the unique property keys. Here's my version:
gremlin> graph = TinkerFactory.createModern()
==>tinkergraph[vertices:6 edges:6]
gremlin> g = graph.traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().properties().key().dedup()
==>name
==>age
==>lang
The problem here is that to do this type of traversal, you will require a full graph scan, which will be problematic if you have a large graph. In those cases you will need to use an OLAP-based traversal with Spark or the like.
If all nodes have a same properties. we can find the properties of the first vertex and generalize it to all nodes:
TinkerGraph tg = TinkerGraph.open() ;
tg.io(IoCore.graphml()).readGraph("src\\main\\resources\\air-routes.graphml");
GraphTraversalSource g = tg.traversal();
g.V().propertyMap().select(Column.keys).next();
// result = {LinkedHashSet#1831} size = 12
// 0 = "country"
// 1 = "code"
// 2 = "longest"
// 3 = "city"
// 4 = "elev"
// 5 = "icao"
// 6 = "lon"
// 7 = "type"
// 8 = "region"
// 9 = "runways"
// 10 = "lat"
// 11 = "desc"
but If there is no guaranty to each node has a same set of properties, I don't find any other solution instead of retrieving all properties in a Map List and find distinct property with java collection methods (outside Gremlin).
The last two lines in the JUnit Test Case might be closer to do what you want.
see also:
https://github.com/BITPlan/com.bitplan.simplegraph/blob/master/simplegraph-core/src/test/java/com/bitplan/simplegraph/core/TestTinkerPop3.java
graph.traversal().V().next().properties()
.forEachRemaining(prop -> System.out.println(String.format("%s=%s",
prop.label(), prop.value().getClass().getSimpleName())));
graph.traversal().V().next().edges(Direction.OUT)
.forEachRemaining(edge -> System.out.println(
String.format("%s->%s", edge.label(), edge.outVertex().label())));
producing:
name=String
age=Integer
created->person
knows->person
JUnit Test Case
#Test
public void testSchema() {
Graph graph = TinkerFactory.createModern();
graph.traversal().V().next().properties()
.forEachRemaining(prop -> System.out.println(String.format("%s=%s",
prop.label(), prop.value().getClass().getSimpleName())));
graph.traversal().V().next().edges(Direction.OUT)
.forEachRemaining(edge -> System.out.println(
String.format("%s->%s", edge.label(), edge.outVertex().label())));
}
Let's say I have a property "name" of nodes in neo4j. Now I want to enforce that there is maximally one node for a given name by identifying all nodes with the same name. More precisely: If there are three nodes where name is "dog", I want them to be replaced by just one node with name "dog", which:
Gathers all properties from all the original three nodes.
Has all arcs that were attached to the original three nodes.
The background for this is the following: In my graph, there are often several nodes of the same name which should considered as "equal" (although some have richer property information than others). Putting a.name = b.name in a WHERE clause is extremely slow.
EDIT: I forgot to mention that my Neo4j is of version 2.3.7 currently (I cannot update it).
SECOND EDIT: There is a known list of labels for the nodes and for the possible arcs. The type of the nodes is known.
THIRD EDIT: I want to call above "node collapse" procedure from Java, so a mixture of Cypher queries and procedural code would also be a useful solution.
I have made a testcase with following schema:
CREATE (n1:TestX {name:'A', val1:1})
CREATE (n2:TestX {name:'B', val2:2})
CREATE (n3:TestX {name:'B', val3:3})
CREATE (n4:TestX {name:'B', val4:4})
CREATE (n5:TestX {name:'C', val5:5})
MATCH (n6:TestX {name:'A', val1:1}) MATCH (m7:TestX {name:'B', val2:2}) CREATE (n6)-[:TEST]->(m7)
MATCH (n8:TestX {name:'C', val5:5}) MATCH (m10:TestX {name:'B', val3:3}) CREATE (n8)<-[:TEST]-(m10)
What results in following output:
Where the nodes B are really the same nodes. And here is my solution:
//copy all properties
MATCH (n:TestX), (m:TestX) WHERE n.name = m.name AND ID(n)<ID(m) WITH n, m SET n += m;
//copy all outgoing relations
MATCH (n:TestX), (m:TestX)-[r:TEST]->(endnode) WHERE n.name = m.name AND ID(n)<ID(m) WITH n, collect(endnode) as endnodes
FOREACH (x in endnodes | CREATE (n)-[:TEST]->(x));
//copy all incoming relations
MATCH (n:TestX), (m:TestX)<-[r:TEST]-(endnode) WHERE n.name = m.name AND ID(n)<ID(m) WITH n, collect(endnode) as endnodes
FOREACH (x in endnodes | CREATE (n)<-[:TEST]-(x));
//delete duplicates
MATCH (n:TestX), (m:TestX) WHERE n.name = m.name AND ID(n)<ID(m) detach delete m;
The resulting output looks like this:
It has to be marked that you have to know the type of the various relationships.
All the properties are copied from the nodes with "higher" IDs to the nodes with the "lower" IDs.
I think you need something like a synonym of nodes.
1) Go through all nodes and create a node synonym:
MATCH (N)
WITH N
MERGE (S:Synonym {name: N.name})
MERGE (S)<-[:hasSynonym]-(N)
RETURN count(S);
2) Remove the synonyms with only one node:
MATCH (S:Synonym)
WITH S
MATCH (S)<-[:hasSynonym]-(N)
WITH S, count(N) as count
WITH S WHERE count = 1
DETACH DELETE S;
3) Transport properties and relationships for the remaining synonyms (with apoc):
MATCH (S:Synonym)
WITH S
MATCH (S)<-[:hasSynonym]-(N)
WITH [S] + collect(N) as nodesForMerge
CALL apoc.refactor.mergeNodes( nodesForMerge );
4) Remove Synonym label:
MATCH (S:Synonym)<-[:hasSynonym]-(N)
CALL apoc.create.removeLabels( [S], ['Synonym'] );
I am following code on Titan Documentation GraphOfTheGodsFactory source code I want to retrieve a vertex from the graph, given some specified value / key / attribute.
I searched on documentation (I am using Titan 0.5.2), and tried using different functions, they provide null when executed.
Things I tried,
`TitanManagement mgmt = graph.getManagementSystem();
final PropertyKey userid = mgmt.makePropertyKey("userid").dataType(Integer.class).make();
TitanGraphIndex namei = mgmt.buildIndex("userid",Vertex.class).addKey(userid).unique().buildCompositeIndex();
TitanTransaction tx = graph.newTransaction();
Vertex ver1 = tx.addVertexWithLabel("user");
ver1.setProperty("userid", "2");
ver1.setProperty("username", "abc");
Vertex found = graph.getVertex("2");`
found returns null.
Please help!
You can't find a Vertex this way:
Vertex found = graph.getVertex("2");
That method looks a vertex up by id, but there is no vertex in the graph with the id of "2" that is a String. Now, because you have ver1, you do know the actual id of that Vertex so you can do:
Vertex found = graph.getVertex(ver1.getId());
Typically, you don't always have that identifier so you want to look things up by your domain data and the indices that you've created. In that case you do:
Vertex found = graph.getVertices("userid","2").next();
That will do an index lookup on your userid property. Since that actually returns an Iterator you have to next() off the result. Obviously, in this case, this only returns one result so no worries about anything else in the Iterator but you should probably account for that in some way in some real code.
How should I get all the existing relationships between each two nodes in a graph in neo4j by java?
I want the results which this cypher query returns:
start r=rel(*) return r
so later I can change or delete some of them based on my conditions?
or get the start or end node of them.
this is what I have done so far:
Iterable<Relationship> rels=GlobalGraphOperations.at(db).getAllRelationships();
for (Relationship rel: rels )
{}
but I have error in this line:for (Relationship rel: rels )
the error is because does not know rels ,and wants to create a class for it.
I used this for indexing and it was working:
GlobalGraphOperations ggo = GlobalGraphOperations.at(db);
for (Relationship r : ggo.getAllRelationships()) {
//indexing code
}
try to get relationships on single node and check result
e.g.
Iterable<BatchRelationship> _itlRelationship= _neo.getRelationships(_empNodeId);
Iterator<BatchRelationship> _itRelationship= _itlRelationship.iterator();
while (_itRelationship.hasNext()) {}