Discovering node properties in neo4j grap db - neo4j

I'm discovering a new graph data model in Neo4j and I was wondering how to list all the possible node properties but not their value if possible.
For the relations, I found this very handy generic cypher query :
start n=node(*)
match n-[r]-m
return distinct type(r)
which return a useful list of properties you can start to use to query more specifically the graph:
==> +------------+
==> | type(r) |
==> +------------+
==> | "RATED" |
==> | "FRIEND" |
==> | "DIRECTED" |
==> | "ACTS_IN" |
==> +------------+
==> 4 rows
==> 0 ms
==>
Is there any function/expression that allows to do this but for the node properties ?
Thanks

type() does not return relationship properties, but the relationship type.
Both nodes and relationships can have properties, but only relationships can have a type.

To list all the properties of nodes in graph DB, you can try using following cypher:
match (n)
WITH distinct keys(n) as properties
UNWIND properties as property
return distinct property
Thanks,
Vishal

Related

Neo4j: Create slef relation cypher query

I have big number of EmpBase imprted (from csv file from postgreSQL )nodes like:
neo4j-sh (?)$ match (e:EmpBase) return e limit 10;
+-------------------------------------------------------------------------+
| e |
+-------------------------------------------------------------------------+
| Node[8992]{neo_eb_id:8993,neo_eb_name:"emp_no_8993",neo_eb_bossID:5503} |
| Node[8993]{neo_eb_id:8994,neo_eb_name:"emp_no_8994",neo_eb_bossID:8131} |
| Node[8994]{neo_eb_id:8995,neo_eb_name:"emp_no_8995",neo_eb_bossID:8624} |
What cypher query can create self relations on every node so that every node with neo_eb_bossid can have the relationship to the adequate node ?
In postgreSQl the data is about 1020MB table. In Neo4j, after import, it is 6.42 GiB as the console says.
In order to create the relationship based on neo_eb_bossID, you can match the nodes and run a foreach loop that will create the relationships to the related node :
MATCH (e:EmpBase) WITH collect(e) AS empbases
FOREACH (emp in empbases |
MERGE (target:EmpBase {neo_eb_id:emp.neo_eb_bossID}
MERGE (emp)-[:YOUR_RELATIONSHIP]->(target)
)
Concerning the self relationship, I've hard to understand what you exactly want.
Chris

Neo4j Graph Traversal excluding nodes

I am trying to find the shortest path between two nodes but I need to exclude some nodes from the path. The cypher that I am trying is
START a=node(1), b=node(2), c=node(3,4)
MATCH p=a-[rel:RELATIONSHIP*]-b
WHERE NOT (c in nodes(p))
RETURN p
ORDER BY length(p) LIMIT 1
But this is giving me a path which includes one of the nodes in c.
Is there a way to do a traversal excluding some nodes?
Thanks
The MATCH ... WHERE part should be fine, but your START clause may not do what you expect. Do the following and consider the result
START a=node(1), b=node(2), c=node(3,4)
RETURN ID(a), ID(b), ID(c)
You get back
==> +-----------------------+
==> | ID(a) | ID(b) | ID(c) |
==> +-----------------------+
==> | 1 | 2 | 3 |
==> | 1 | 2 | 4 |
==> +-----------------------+
That means the rest of the query is executed twice, once excluding (3) from the path and once excluding (4). But that also means of course that it is run once not excluding each of them, which means you can indeed get results with those nodes present on the path.
If you want to exclude both of those nodes from the path, try collecting them and filtering with NONE or NOT ANY or similar. I think something like this should do it (can't test at the moment).
START a=node(1), b=node(2), c=node(3,4)
WITH a, b, collect (c) as cc
MATCH p=a-[rel:RELATIONSHIP*]-b
WHERE NONE (n IN nodes(p) WHERE n IN cc)
RETURN p
ORDER BY length(p) LIMIT 1

Potential inconsistency in creating relationships in cypher when we don't use directions

I am getting confused with the way relationships are created through cypher. I was under the impression that _src-[:likes]- _dst creates a bidirectional relationship but looks like that is not the case as _src-[:likes]- _dst == _src<-[:likes]- _dst (example provided below)
Let's say I create the following graph but using the _src[:likes]-_dst notation ( using '-' as opposed to '->')
create
(_u1 {type:"User",`name`:"u1",userId:'u1' }) , ( _u2 {type:"User",`name`:"u2",userId:'u2'} ) , ( _u3 {type:"User",`name`:"u3",userId:'u3' }) , ( _u4 {type:"User",`name`:"u4",userId:'u4' }) , ( _u5 {type:"User",`name`:"u5",userId:'u5'}) , (_u6 {type:"User",`name`:"u6",userId:'u6'}),
(_f1 {type:"Item",`name`:"f1",itemId:'f1' }) , ( _f2 {type:"Item",`name`:"f2",itemId:'f2' }) , ( _f3 {type:"Item",`name`:"f3",itemId:'f3' }) , ( _f4 {type:"Item",`name`:"f4",itemId:'f4'}) , (_f5 {type:"Item",`name`:"f5",itemId:'f5'}),
_u1-[:`likes`{likeValue:3}]-_f1 , _u1-[:`likes` {likeValue:13}]-_f2 , _u1-[:`likes` {likeValue:1}]-_f3 , _u1-[:`likes` {likeValue:5}]-_f4,
_u2-[:`likes`{likeValue:7}]-_f1 , _u2-[:`likes` {likeValue:13}]-_f2 , _u2-[:`likes` {likeValue:1}]-_f3,
_u3-[:`likes`{likeValue:5}]-_f1 , _u3-[:`likes` {likeValue:8}]-_f2 , _u4-[:`likes`{likeValue:5}]-_f1
,_u5-[:`likes` {likeValue:8}]-_f2,_u6-[:`likes` {likeValue:8}]-_f2;
My impression was this way, you tell neo4j to created a bidirectional relationship. Now, look at the following query
neo4j-sh (?)$ start n=node(*) match n-[:likes]->m where has(n.type) and n.type='User' return n,m;
==> +-------+
==> | n | m |
==> +-------+
==> +-------+
==> 0 row
But the opposite works
neo4j-sh (?)$ start n=node(*) match n-[r]->m where has(n.type) and n.type="Item" return n,m limit 3;
==> +-----------------------------------------------------------------------------------------+
==> | n | m |
==> +-----------------------------------------------------------------------------------------+
==> | Node[7]{type:"Item",name:"f1",itemId:"f1"} | Node[4]{type:"User",name:"u4",userId:"u4"} |
==> | Node[7]{type:"Item",name:"f1",itemId:"f1"} | Node[3]{type:"User",name:"u3",userId:"u3"} |
==> | Node[7]{type:"Item",name:"f1",itemId:"f1"} | Node[2]{type:"User",name:"u2",userId:"u2"} |
==> +-----------------------------------------------------------------------------------------+
The question is why a-[:likes]-b = a<-[:likes]-b ?
Now I create two more nodes and a relationship as instructed in the Cypher manual
create (_u7 {type:"User",`name`:"u7",userId:'u7' });
create (_f7 {type:"Item",`name`:"f7",itemId:'f7' });
start src=node(*),dst=node(*) where src.name='u7' and dst.name='f7' create src-[:likes{likeValue:3}]-dst;
neo4j-sh (?)$ start n=node(*) match n-[r]->m where has(n.type) and n.type="User" return n,m limit 3;
==> +-------+
==> | n | m |
==> +-------+
==> +-------+
==> 0 row
same results, we can't query from User to Item but we can from Item to User
now if use the following method things change
create (_u {type:"User",`name`:"u8",userId:'u8' }) , ( _f {type:"User",`name`:"f8",userId:'f8'} ), _u-[:likes{likeValue:2}]-_f;
neo4j-sh (?)$ start n=node(*) match n-[r]->m where has(n.type) and n.type="User" return n,m limit 3;
==> +-------------------------------------------------------------------------------------------+
==> | n | m |
==> +-------------------------------------------------------------------------------------------+
==> | Node[19]{type:"User",name:"f8",userId:"f8"} | Node[18]{type:"User",name:"u8",userId:"u8"} |
==> +-------------------------------------------------------------------------------------------+
What is going on? These are my questions
1- Why create _src-[:likes]-_dst does not create a bidirectional relationship?
2- If it can't then why even allow _src-[:likes]-_dst for relationship creation? Why not force people to use directions when creating relationships?
3- What is the difference between the two methods I used to create relationships? (u7-f7 and u8-f8)
You can't create a bidirectional relationship using _src[:likes]-_dst
In Neo4j, a relation can and must only have a single direction. So to represent bidirectional, you have two options:
a) Create the relation with a direction but ignore when querying (_src[:likes]-_dst will match both directions when part of a match clause)
b) Create two relations- one in either direction
It appears that if you execute a create without a direction such as _src[:likes]-_dst, an incoming relation is created for _src

Neo4j Cypher: Find exact match to array Node property in WHERE clause

Given a Neo4J Node with an array property, how do I create a Cypher query to return only the node(s) that match an array literal?
Using the console I created a node with the array property called "list":
neo4j-sh (0)$ create n = {list: [1,2,3]};
==> +-------------------+
==> | No data returned. |
==> +-------------------+
==> Nodes created: 1
==> Properties set: 1
==> 83 ms
neo4j-sh (0)$ start n=node(1) return n;
==> +-----------------------+
==> | n |
==> +-----------------------+
==> | Node[1]{list:[1,2,3]} |
==> +-----------------------+
==> 1 row
==> 1 ms
However, my query does not return the Node that was just created given a WHERE clause that matches an array literal:
neo4j-sh (0)$ start n=node(1) where n.list=[1,2,3] return n;
==> +---+
==> | n |
==> +---+
==> +---+
==> 0 row
==> 0 ms
It's entirely possible I'm mis-using Cypher. Any tips on doing exact array property matching in Cypher would be helpful.
The console is always running the latest SNAPSHOT builds of Neoj4. the version refers to the Cypher Syntax parswer, we will point that out more clearly :)
Now, there has been some fixing around the Array handling in Cypher, see https://github.com/neo4j/community/pull/815 and https://github.com/neo4j/community/issues/818 which problably are the ones that make the console work. This has been merged in after 1.8.M07, so in order to get it work locally, please download one of the latest 1.8.-SNAPSHOT, build it from GITHUB or wait for 1.8.M08 which is due very soon.
/peter
Which version of Neo4j are you using?
Your same code works for me in 1.8M07.
http://console.neo4j.org/?id=p9cy6l
Update:
I get the same result (no results) in a local install via the web client. Maybe it's a web client issue?

understanding cypher output

I have a graph like this:
(2)<-[0:CHILD]-(1)-[1:CHILD]->(3)
In words: Node 1,2 and 3 (all with names); Edges 0 and 1
I write the following cypher-query:
START nodes = node(1,2,3), relationship = relationship(0,1)
RETURN nodes, relationship
and got as a result:
==> +-----------------------------------------------+
==> | nodes | relationship |
==> +-----------------------------------------------+
==> | Node[1]{name->"Risikogruppe2"} | :CHILD[0] {} |
==> | Node[1]{name->"Risikogruppe2"} | :CHILD[1] {} |
==> | Node[2]{name->"Beruf 1"} | :CHILD[0] {} |
==> | Node[2]{name->"Beruf 1"} | :CHILD[1] {} |
==> | Node[3]{name->"Beruf 2"} | :CHILD[0] {} |
==> | Node[3]{name->"Beruf 2"} | :CHILD[1] {} |
==> +-----------------------------------------------+
==> 6 rows, 0 ms
now my question:
why I became all nodes twice and relationships three time? I just want to get all of it one time.
thanks for your time ^^
The way Cypher works is very similar to SQL. When you create your variables in your START clause, you're sort of doing a from nodes, relationships in SQL (tables). The reason you're getting a cartesian product of all of the possible values for the two, is because you're not doing any sort of match or where to filter them, so it's basically like:
select *
from nodes, relationships
Where you forgot to put the foreign key relationship between the tables.
In Cypher, you do this by doing a match, usually:
start n=node(1,2,3), r=relationship(0,1)
match n-[r]-m // find where the n nodes and the r relationships point (to m)
return *
But since you have no match, you get a cartesian product.
You should only see the nodes and relationships once, unless you do some matching.
Tried to reproduce your problem, but I haven't been able to.
http://tinyurl.com/cobd8oq
Is it possible for you to create an console.neo4j.org example of your problem?
Thanks,
Andrés

Resources