Apache AGE-How to create a directed Edge - apache-age

I have created a graph named 'family tree' and have added three persons with the label Persons.
Now i'm adding an edge between Andrew James and Timathy James such that, Andrew is the son of Timathy using the following command:
Now when I display the edges I get:
I am getting that Andrew is the son of Timathy, and also the opposite. What am I doing wrong here.
PS: Let's ignore the year_born and year_died for now.

In your last query, you are missing the >. It should be:
MATCH (a:Person)-[e:Son_of]->(b:Person)

MATCH (a)-[e]-(b) checks for incoming or outgoing edges for each vertex in given pattern.
Suppose there is a pattern created like (a)-[e]->(b). Now the way MATCH (a)-[e]-(b) works is, it will see for vertex 'a', if there is any edge 'e' outgoing or incoming towards it from 'b'. Now it will see for vertex 'b', if there is any edge 'e' outgoing or incoming towards it from 'a'.
In this case, 'a' has an outgoing edge 'e' towards 'b', and 'b' has incoming edge 'e' from 'a'. Hence output is kind of duplicated with just vertices opposite. If you display the start and end id of edge, you will notice that it is same for both results, just the vertices are opposite in output.
Adding > to your MATCH query (as answered above by rafsun) should resolve your question.

So actually what is happening in this query is that you are creating an edge and not a directed edge, which is why it is giving you this result.
Add -> for the directed edge in the above query and rerun it. It will surely work
Now when you add '->' at the red circled thing it will indicate that a is the son of b.

Related

Open Street Map tag to grab all emerged land

I'm looking to download the geometries of all emerged land (everything within the coastal line) in Python using OSMNX, but can't seem to find a general tag that would do it.
Right now, I'm using:
t = {'landuse':['commercial', 'industrial', 'residential', 'farmland', 'construction', 'education', 'retail', 'cemetery', 'grass', 'garages', 'depot', 'port', 'railway', 'recreation_ground', 'religious', 'yes', '*'], 'leisure':['park']}
land = ox.geometries_from_polygon(bbox, tags=t)
But I still have many holes...
So, in short, is there an OSM tag to grab all emerged land?
The additive approach, i.e. combining all sorts of landuses, won't get you all the way to the result you want. As you've noticed, you'll end up with white spots. You could get closer by considering even more tags, such as some values of the natural=* key, but ultimately there simply is land that is not covered by any such polygon in OSM.
Instead, you should look at OSM coastline data. As this can be tricky to process, you might want to get pre-processed data from osmdata.openstreetmap.de, such as their land polygons.

Gremlin: Generate a list by location of counts for active versus inactive users

I have vertices people, usertype, and location. People has outgoing edges people_location and people_usertype. People has property 'name', usertype has property 'activationStatus', and location has property 'name'.
I want to create a list that looks like this:
[[1]: https://i.stack.imgur.com/lKzZL.png]
I want the count of people, by location, for activationStatus "active" and "inactive" where the location has "US" in it.
This is all I have only for count of people by location where the location 'name' begins with US:
g.V()hasLabel('people').out('people_publicisofficelocation')
.filter(has('name',between('US','UT')))
.groupCount().by('name')
It is running but not yielding results.
You can simulate 'starts with' behavior in versions of TinkerPop prior to 3.4 using something like has('name',between('US','UT')) so you could replace the filter line above with that. If the graph implementation you are using supports TinkerPop 3.4 there are additional text predicates you can use for begins with, ends with and contains.
As others have said if you can post some sample addV() and addE() steps that build part of your graph it will be easier to give a more precise answer.
This worked for me!
g.V().hasLabel('Location').filter(has('name',between('US','UT')))
.project('Name','Active', 'Inactive', 'Total')  .by('name')  .by(__.both('people_location').out('people_usertype')
.where(values('activationStatus').is(eq('Active'))).count())  .by(__.both('people_location').out('people_usertype')
.where(values('activationStatus').is(eq('Inactive'))).count()) 
.by(__.both('people_location').out('people_usertype').count())

How do I update a specific edge property using Gremlin/Titan/TinkerPop3?

The goal
I have a simple enough task to accomplish: Set the weight of a specific edge property. Take this scenario as an example:
What I would like to do is update the value of weight.
Additional Requirements
If the edge does not exist, it should be created.
There may only exist at most one edge of the same type between the two nodes (i.e., there can't be multiple "votes_for" edges of type "eat" between Joey and Pizza.
The task should be solved using the Java API of Titan (which includes Gremlin as part of TinkerPop 3).
What I know
I have the following information:
The Vertex labeled "user"
The edge label votes_for
The value of the edge property type (in this case, "eat")
The value of the property name of the vertex labeled "meal" (in this case "pizza"), and hence also its Vertex.
What I thought of
I figured I would need to do something like the following:
Start at the Joey vertex
Find all outgoing edges (which should be at most 1) labeled votes_for having type "eat" and an outgoing vertex labeled "meal" having name "pizza".
Update the weight value of the edge.
This is what I've messed around with in code:
//vertex is Joey in this case
g.V(vertex.id())
.outE("votes_for")
.has("type", "eat")
//... how do I filter by .outV so that I can check for "pizza"?
.property(Cardinality.single, "weight", 0.99);
//... what do I do when the edge doesn't exist?
As commented in code there are still issues. Would explicitly specifying a Titan schema help? Are there any helper/utility methods I don't know of? Would it make more sense to have several vote_for labels instead of one label + type property, like vote_for_eat?
Thanks for any help!
You are on the right track. Check out the vertex steps documentation.
Label the edge, then traverse from the edge to the vertex to check, then jump back to the edge to update the property.
g.V(vertex.id()).
outE("votes_for").has("type", "eat").as("e").
inV().has("name", "pizza").
select("e").property("weight", 0.99d).
iterate()
Full Gremlin console session:
gremlin> Titan.version()
==>1.0.0
gremlin> Gremlin.version()
==>3.0.1-incubating
gremlin> graph = TitanFactory.open('inmemory'); g = graph.traversal()
==>graphtraversalsource[standardtitangraph[inmemory:[127.0.0.1]], standard]
gremlin> vertex = graph.addVertex(T.label, 'user', 'given_name', 'Joey', 'family_name', 'Tribbiani')
==>v[4200]
gremlin> pizza = graph.addVertex(T.label, 'meal', 'name', 'pizza')
==>v[4104]
gremlin> votes = vertex.addEdge('votes_for', pizza, 'type', 'eat', 'weight', 0.8d)
==>e[1zh-38o-4r9-360][4200-votes_for->4104]
gremlin> g.E(votes).valueMap(true)
==>[label:votes_for, weight:0.8, id:2rx-38o-4r9-360, type:eat]
gremlin> g.V(vertex.id()).outE('votes_for').has('type','eat').as('e').inV().has('name','pizza').select('e').property('weight', 0.99d).iterate(); g.E(votes).valueMap(true)
==>[label:votes_for, weight:0.99, id:2rx-38o-4r9-360, type:eat]
Would explicitly specifying a Titan schema help?
If you wanted to start from the Joey node without having a reference to the vertex or its id, this would be a good use case for a Titan composite index. The traversal would start with:
g.V().has("given_name", "Joey")
Are there any helper/utility methods I don't know of?
In addition to the TinkerPop reference documentation, there are several tutorials that you can read through:
Getting Started
The Gremlin Console
Recipes
Would it make more sense to have several vote_for labels instead of one label + type property, like vote_for_eat?
Depends on what your graph model or query patterns are, but more granular labels like vote_for_eat can work out fine. You can pass multiple edge labels on the traversal step:
g.V(vertex.id()).outE('vote_for_eat', 'vote_for_play', 'vote_for_sleep')
Update
There may only exist at most one edge of the same type between the two nodes
You can use the Titan schema to help with this, specifically define an edge label with multiplicity ONE2ONE. An exception will be thrown if you create more than one votes_for_eat between Joey and pizza.
Jason already answered nearly all of your questions. The only aspect missing is:
If the edge does not exist, it should be created.
So I'll try to answer this point with a slightly different query. This query adds a new edge if it doesn't exist already and then updates / adds the weight property:
g.V(vertex.id()).outE('votes_for').has('type', 'eat')
.where(__.inV().hasLabel('meal').has('name','pizza')) // filter for the edge to update
.tryNext() // select the edge if it exists
.orElseGet({g.V(vertex.id()).next()
.addEdge('votes_for', g.V(pizzaId).next(), 'type', 'eat')}) // otherwise, add the edge
.property('weight', 0.99) // finally, update / add the 'weight' property

The provided start does not map to a value

I have a traversal as follows:
g.V().hasLabel("demoUser")
.as("demoUser","socialProfile","followCount","requestCount")
.select("demoUser","socialProfile","followCount","postCount")
.by(__.valueMap())
.by(__.out("socialProfileOf").valueMap())
.by(__.in("followRequest").hasId(currentUserId).count())
.by(__.outE("postAuthorOf").count())
I'm trying to select a user vertex, their linked social profile vertex, and some other counts. The issue is that all users may not have a socialProfile edge. When this is the case the traversal fails with the following error:
The provided start does not map to a value: v[8280]->[TitanVertexStep(OUT,[socialProfileOf],vertex), PropertyMapStep(value)]
I did find this thread from the gremlin team. I tried wrapping the logic inside of .by() with a coalesce(), and also appending a .fold() to the end of the statement with no luck.
How do I make that selection optional? I want to select a socialProfile if one exists, but always select the demoUser.
coalesce is the right choice. Let's assume that persons in the modern graph have either one or no project associated with them:
gremlin> g.V().hasLabel("person").as("user","project").
select("user","project").by("name").by(coalesce(out("created").values("name"),
constant("N/A")))
==>{user=marko, project=lop}
==>{user=vadas, project=N/A}
==>{user=josh, project=ripple}
==>{user=peter, project=lop}
Another way would be to completely exclude it from the result:
g.V().hasLabel("person").as("user","project").choose(out("created"),
select("user","project").by("name").by(out("created").values("name")),
select("user").by("name"))
But obviously this will only look good if each branch returns a map / selects more than 1 thing, otherwise you're going to have mixed result types.

InstantiationException when using traversedElement

I'm attempting to setup a Graph which allows a query to follow "Redirect" edges from one vertex to another.
Vertices can only have a single Redirect edge going out; however, there may be a chain of Redirects that occur before reaching the final destination.
I'm attempting to grab the final vertex using the traversedElement function; however, even when I strip my implementation down to a query as simple as
select traversedElement(-1) from (traverse out() from #15:2)
I'm receiving the following error:
java.lang.InstantiationException: com.orientechnologies.orient.core.sql.functions.coll.OSQLFunctionTraversedElement
I'm not sure what the best way to debug this one might be, the simplified query I'm attempting above appears to match the documentation faithfully (documentation example):
SELECT traversedElement(-1) FROM ( TRAVERSE out() from #34:3232 WHILE $depth <= 10 )
Any words of wisdom would be greatly appreciated, thanks!
There was an issue with traversedElement() on last release (fixed on 2.0.7-SNAPSHOT). However you can use traversedEdge() and traversedVertex() that works.