How to find graph schema in Gremlin? - java

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())));
}

Related

How does searching for a vertex happen in graph databases using gremlin (Apache TinkerPop)?

I am working on modeling my data such as ->
data: [
{
id:"123",
type:"a",
attributes: [...]
},
{entity 2 ...},
{entity 3 ...},
...
]
Is there a gremlin query I can use to fetch/get the vertex by type and id instead of just id?
If not, would I have to traverse and search, if so what would the performance look like?
Type of entity in Gremlin is called Label.
To get a vertex by id and verify it has specific label you can run the query:
g.V('123').hasLabel('a').next()
If type is just a regular property (attribute) you can run:
g.V('123').has('type', 'a').next()
Performance depends on implementation, but getting vertex by id should be O(1) in any case.

Can we convert Result in ResultSet to Vertex by using gremlin - java client?

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".

Is there any simple way of Comparing two graphs in neo4j

My back-end generates a graph that contains a node (lets call it Node 1), the graph looks as follows
1 (TOPNODE)
/ \
2 1 2
/ \
3 3 4
/ \
4 5 6
The top node contains the date the graph was generated.
After that all the even levels (level 2 and level 4 which contain nodes 1, 2,5 and 6) contain a unique name, and a value ie. a phone number.
All of the odd levels (level 3 AKA: nodes 3 and 4) contain their parent name and their children information.
In my service I can edit parts of the graph. For example: I can change the value in the node (NOT THE NAME). or I can delete nodes at once. But i cna only access the edited information by generating that part of the subgraph.
SO my question is: Can I get the full graph into JAVA, then compare only that subgraph with the new subgraph that was just generated and then create a new version of the old graph but with the changes?
What I have tried is:
pulling all of the graph into java as a JSON, and using that to compare to the smaller graph, this works. But I dont know if there is a more efficient way or if there is any way to get the nodes in java as actual nodes instead of JSON. To get it into a JSON I did the following:
Session session = driver.session();
String message = "START n=node(*) MATCH (n)-[r]->(m) RETURN n,r,m;";
StatementResult result = session.run(message);
while ( result.hasNext() ) {
Record record = result.next();
Gson gson = new Gson();
System.out.println(gson.toJson(record.asMap()));
String m = gson.toJson(record.asMap().get("n"));
JSONObject json = new JSONObject(gson.toJson(record.asMap()));
convert(json,m);
}
session.close();

OrientDB vertex relationships efficient search

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);

How to get Vertex from provided attribute / key in Titan

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.

Categories

Resources