neo4j Cypher Query - graph

i have a following graph in neo4j graph database and by using the cypher query language, i want to retrieve the whole data with is connected to root node and their child node.
For example :
kindly find the below graph image.
[As per the image, node 1 has two child and their child also have too many child with the same relationship. now what i want, using Cypher, i hit the node 1 and it should response with the whole data of child node and there child node and so on, relationship between nodes are "Parent_of" relationship.]
can anyone help me on this.

start n=node(1) // use the id, or find it using an index
match n-[:parent_of*0..]->m
return m
will get you all the graph nodes in m. You could also take m.some_property instead of m if you don't want the node itself, but some property that is stored in your nodes.
Careful though, as the path has no limit, this query could become pretty huge in a large graph.

You can see an example of *0.. here: http://gist.neo4j.org/?6608600

Related

gremlin traversal on AWS neptune

I have a graph structure like this-
Node1(Console) <----Uses--- Node2(Name, Age) -----plays----> Node3(Game)
So, i have three nodes -
Node1 is console like a PS3/ Nintendo.
Node2 is a person with properties name and Age.
Node3 is game node which holds game name like 'warcraft'.
Now I want to have a gremlin query which tells me that.
How many users (Node2) who has the console like PS3, plays a game like 'warcraft'
I think i need to start the traverse from Node2 , filter it based on Node1 property i.e console as as 'PS3' and plays game like 'warcraft'
I am new to gremlin and using some thing like this -
g.V().hasLabel('user').outE('uses').inV().has('console', 'ps3').count()
the above query only answers half of my required result. How do i filter Node2 based on plays relationship as well.
Any help is appreciated.
There are multiple ways to write the query.
Option 1: Start from console
g.V().has('console', 'ps3').in('uses').where(out('plays').has('game', 'warcraft')).valueMap('name')
Let me explain the structure here:
g.V().has('console', 'ps3') --> Select all vertices which have a property with key as console and value as ps3
in('uses') --> From the set of previous vertices, jump to incoming vertices via an edge that has the label uses. At this stage, we would have player vertices in our solution.
where(out('plays').has('game', 'warcraft')) --> Apply a filter on existing solutions. Since we are using where we would not jump/traverse to the next step of vertices.
valueMap('name') --> Project one or more properties if existing solutions which are player vertices.
Option 2: Another way to write above query
g.V().has('console', 'ps3').in('uses').as('myusers').out('plays').has('game', 'warcraft').select('myusers').by('name')
as('myusers') --> Provides a reference/alias to the vertices at this stage. Note that it does not store all the results at this stage instead it just provides a reference to the type of vertices at this point in the query.
out('plays').has('game', 'warcraft') --> Unlike previous time when we did not jump since we were using where, this time we jump onto the game vertices.
select('myusers').by('name') --> since we want to project the users but the current solutions are game vertices, we need to select the user vertices which we do using the reference we stored earlier.
Option 3: Start from user
g.V().hasLabel('user').where(out('plays').has('game','warcraft')).where(out('uses').has('console','ps3')).valueMap('name')
There are more ways to write this query such as using path() but I won't go into details here.
Since you are beginning to learn Gremlin, I would recommend that you start with https://kelvinlawrence.net/book/Gremlin-Graph-Guide.html

From a given node get reachable node following unidirectional relationship and display that sub-graph as a tree

here is my problem:
I've got a graph where I have :Item with one relationship :CRAFTED_WITH to one :RECIPE and those :RECIPEhave one or more relationship :COMPOSED_OF{quantity} to ingredients that are :Item.
As you can imagine you can have several level of relationship to get from a high tier :Item to the most basic of components.
I want to be able to find all nodes that are reachable from a specific node while following only one direction. That part was easy I used the apoc procedure apoc.path.subgraphAll.
But now my next step is to have the result display as a tree and not a graph. In a graph I will ended up with multiple :Item on the receiving end of :COMPOSED_OF relationship. I want :Item to be "duplicated" so they are linked by a single :COMPOSED_OF relationship.
Is it even feasible only in cypher ? Or will I have to use another language to handle a graph to turn it into that "tree" structure ?
There is an apoc function to do that. The cypher below illustrates what is does.
MATCH treePath=(root:Thing)-[:CHILD*0..]->(leaf:Thing)
WHERE NOT (leaf)-[:CHILD]->()
AND NOT ()-[:CHILD]->(root)
WITH COLLECT(treePath) AS treePaths
CALL apoc.convert.toTree(treePaths) yield value AS tree
RETURN tree

Janusgraph - How to hide the edge relation between two vertices and establish / retrieve again based on a condition?

I'm new to the Janusgraph Database. I have a requirement where I need to hide the relation (edge) between two vertices without dropping them and later I should able retrieve / establish the same relation again between those vertices based on condition.
I only know how to drop the edges but I don't know how to retrieve/restore the relation again. Could you please help me out here.
Thanks a lot for your time.
If you want to 'restore' the connections I think you shouldn't drop them at all.
Just keep a property on the edge that indicates the edge state (active/inactive) or maybe keep a start and end date on the edge.
This way when you traverse your graph you need to makes sure to use only the active edges, but the old ones can still easily found if you want to restore them.
for example:
g.addV('person').property('id', 'bob').property('name', 'Bob')
g.addV('person').property('id', 'alice').property('name', 'Alice')
g.addV('person').property('id', 'eve').property('name', 'Eve')
g.V('bob').addE('friend').to(g.V('alice'))
g.V('bob').addE('friend').to(g.V('eve'))
So Bob friends with Alice and Eve:
g.V('bob').out('friend').values("name")
==>Alice
==>Eve
Let say Bob and Alice had a fallout, and they are no longer friends:
g.V('bob').outE('friend').where(inV().hasId('alice')).property('status', 'inactive')
now you can query only Bob active friends, without dropping the old edges:
g.V('bob').outE('friend').not(has('status', 'inactive')).inV().values("name")
==> Eve

How to get a path from one node to another including all other nodes and relationships involved in between

I have designed a model in Neo4j in order to get paths from one station to another including platforms/legs involved. The model is depicted down here. Basically, I need a query to take me from NBW to RD. also shows the platforms and legs involved. I am struggling with the query. I get no result. Appreciate if someone helps.
Here is my cypher statement:
MATCH p = (a:Station)-[r:Goto|can_board|can_alight|has_platfrom*0..]->(c:Station)
WHERE (a.name='NBW')
AND c.name='RD'
RETURN p
Model:
As mentioned in the comments, in Cypher you can't use a directed variable-length relationship that uses differing directions for some of the relationships.
However, APOC Procedures just added the ability to expand based on sequences of relationships. You can give this a try:
MATCH (start:station), (end:station)
WHERE start.name='NBW' AND end.name='THT'
CALL apoc.path.expandConfig(start, {terminatorNodes:[end], limit:1,
relationshipFilter:'has_platform>, can_board>, goto>, can_alight>, <has_platform'}) YIELD path
RETURN path
I added a limit so that only the first (and shortest) path to your end station will be returned. Removing the limit isn't advisable, since this will continue to repeat the relationships in the expansion, going from station to station, until it finds all possible ways to get to your end station, which could hang your query.
EDIT
Regarding the new model changes, the reason the above will not work is because relationship sequences can't contain a variable-length sequence within them. You have 2 goto> relationships to traverse, but only one is specified in the sequence.
Here's an alternative that doesn't use sequences, just a whitelisting of allowed relationships. The spanningTree() procedure uses NODE_GLOBAL uniqueness so there will only be a single unique path to each node found (paths will not backtrack or revisit previously-visited nodes).
MATCH (start:station), (end:station)
WHERE start.name='NBW' AND end.name='RD'
CALL apoc.path.spanningTree(start, {terminatorNodes:[end], limit:1,
relationshipFilter:'has_platform>|can_board>|goto>|can_alight>|<has_platform'}) YIELD path
RETURN path
Your query is directed --> and not all of the relationships between your two stations run in the same direction. If you remove the relationship direction you will get a result.
Then once you have a result I think something like this could get you pointed in the right direction on extracting the particular details from the resulting path once you get that working.
Essentially I am assuming that everything you are interested in is in your path that is returned you just need to filter out the different pieces that are returned.
As #InverseFalcon points out this query should be limited in a larger graph or it could easily run away.
MATCH p = (a:Station)-[r:Goto|can_board|can_alight|has_platfrom*0..]-(c:Station)
WHERE (a.name='NBW')
AND c.name='THT'
RETURN filter( n in nodes(p) WHERE 'Platform' in labels(n)) AS Platforms

How do i get all nodes in the graph on a certain relation ship type

I have build a small graph where all the screens are connected and the flow of the screen varies based on the system/user. So the system/user is the relationship type.
I am looking to fetch all nodes that are linked with a certain relation ship from a starting screen. I don't care about the depth since i don't know the depth of the graph.
Something like this, but the below query takes ever to get the result and its returning incorrect connections not matching the attribute {path:'CC'}
match (n:screen {isStart:true})-[r:NEXT*0..{path:'CC'}]-()
return r,n
A few suggestions:
Make sure you have created an index for :screen(isStart):
CREATE INDEX ON :screen(isStart);
Are you sure you want to include 0-length paths? If not, take out 0.. from your query.
You did not specify the directionality of the :NEXT relationships, so the DB has to look at both incoming and outgoing :NEXT relationships. If appropriate, specify the directionality.
To minimize the number of result rows, add a WHERE clause that ensures that the current path cannot be extended further.
Here is a proposed query that combines the last 3 suggestions (fix it up to suit your needs):
MATCH (n:screen {isStart:true})-[r:NEXT* {path:'CC'}]->(x)
WHERE NOT (x)-[:NEXT {path:'CC'}]->()
return r,n;

Resources