What is the appropriate cypher query? - neo4j

I am trying to run the web ui on
7474/webadmin/#
Suppose I want to find a node that has a property "title" with a value of "Home".
How do I find that node using a cypher query? (There should be only one node.)
Also, suppose I want to retrieve a relationship?
Let's say I have the following:
A -entitledTo-> B -entitledTo-> C
I have already tried the following:
start n=node(*) where n.title='Home' return n;
start c=node(node_c_id) match a-[:entitledTo]->b-[:entitledTo]->c return a,b,c;
However, I get this error message: The property 'title' does not exist on Node[0]
How do I resolve this issue?
Lastly, this is version 2.0.0-M03

use:
start n=node(*) where has(n.title) and n.title='Home' return n
In general you should consider using indexes for this kind of operation, Neo4j's reference manual has lots of information about this.

You can use:
start n=node(*) where n.title! ='Home' return n;
See the section on missing properties in where clauses

To retrieve the Relationships, perhaps the Cypher PATH command could be usefull.

Related

How to find a node quick in Neo4J 3.3.9 - cypher query optimization

I have the following Neo4J DB model:
I need to be able to find a node of the type Concept called "idea" made by the user infranodus and see which nodes of the type Context it is connected to.
I use the following query, but it's taking too long and doesn't even load...
MATCH (ctx:Context)-[:BY]->(u:User{name:'infranodus'})
WITH DISTINCT ctx
MATCH (c:Concept{name:'idea'})-[:AT]->(ctx)<-[:AT]-(cn:Concept)
RETURN DISINCT c, ctx, count(cn);
How to fix it?
adding indexes to the neo4j database would be helpful ( i didnt see any there ) then start your match with the indexed node and traverse from there. i think that having a
MATCH (c:Concept{name:'idea'})-[:AT]->(ctx)<-[:AT]-(cn:Concept)
WHERE (ctx)-[:BY]->(u:User{name:'infranodus'})
....
would also avoid querying twice.
Create an index on the name property of nodes with the User label - a unique index would be great for this.
An index for the name property on concept would be good, too (probably without uniqueness constraint - even though you're looking for distinct nodes explicitly).
Start your query from there.
MATCH (u:User {name:'infranodus'})
MATCH (c:Concept {name: 'idea'})
MATCH (u)<-[:BY]-(ctx:Context)<-[:AT]-(c)
MATCH (c:Concept{name:'idea'})-[:AT]->(ctx)<-[:AT]-(cn:Concept)
RETURN c, ctx, size((c)-[:AT]->(ctx)<-[:AT]-(:Concept))
Doesn't look as nice, but you're asking for query tuning. Make sure to PROFILE your existing query and this. Plus, you had a typo in your query after your return keyword.

need help on cypher query

I need some help to do a cypher query.
In my neo4j databases I have element nodes which are linked by relation nodes (not relationship) and I would like to find all nodes that inherit from a node. For example if I have B-->A, c-->B and D-->A where "-->" means "inherit" I would like to retrieve B, C and D when I ask to retrieve which elements are inherit from A.
I already written a cypher query which is working well on a single level (where I replace "A" by the node id) :
Start
node=node(A)
match
(node)-[:IS_SOURCE_OF]->relation<-[:IS_TARGET_OF]-target
where
relation.relationType="INHERIT"
return target.uuid
This query returns B and D but I don't know how to return C as well.
Does someone can help me please ?
Thanks a lot
Cypher allows variable length matches on single relationships, but not the way you have designed your graph. To find the node c in your example you need to do:
Start node=node(A)
match (node)-[:IS_SOURCE_OF]->(r1)<-[:IS_TARGET_OF]-()-[:IS_SOURCE_OF]->(r2)<-[:IS_TARGET_OF]-(target)
where
r1.relationType="INHERIT" AND r2.relationType="INHERIT"
return target.uuid
However you should take a step back and rethink if you cannot model the inheritance relationship explicitly - in this case a single query catches all inherited nodes from a
start node=node(a)
match node-[:INHERITS*]->target
return target.uuid

Neo4j Cypher version 1.8 : Probable bug with relationship identifiers

http://console.neo4j.org/r/yx62bk
In the graph above, the query
start n=node(7,8,9)
match n-[objectScore:score]->o-[:object_of_destination]->d<-[:destination_score]-n,
o-[:instance_of]->ot, o-[:date]->oDate, d-[:date]->dDate where ot.name='HOTEL'
return n, o, objectScore, d;
returns o as null.
Change the query to remove relationship identifier - objectScore
start n=node(7,8,9)
match n-[:score]->o-[:object_of_destination]->d<-[:destination_score]-n,
o-[:instance_of]->ot, o-[:date]->oDate, d-[:date]->dDate where ot.name='HOTEL'
return n, o, objectScore, d;
and the output returns o node correctly.
For my scenario I need both of them. Not sure How to do that? Any suggestions on this.
Nice find. We track Cypher issues on github, so I've opened an issue about it there: https://github.com/neo4j/community/issues/837
Thanks so much for reporting it!
Edit: I've found the problem. A simple workaround is to, ironically, introduce an optional relationship. The problem is located in one of the matchers Cypher can use, and by marking a piece of your pattern as optional, you force Cypher to use a different matcher. If you want to
So, change your MATCH to this:
match n-[objectScore:score]->o-[:object_of_destination]->d<-[:destination_score]-n,
o-[:instance_of]->ot,
o-[:date]->oDate,
d-[?:date]->dDate
A real fix is in the works.

Return node if relationship is not present

I'm trying to create a query using cypher that will "Find" missing ingredients that a chef might have, My graph is set up like so:
(ingredient_value)-[:is_part_of]->(ingredient)
(ingredient) would have a key/value of name="dye colors". (ingredient_value) could have a key/value of value="red" and "is part of" the (ingredient, name="dye colors").
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
I'm using this query to get all the ingredients, but not their actual values, that a recipe requires, but I would like the return only the ingredients that the chef does not have, instead of all the ingredients each recipe requires. I tried
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef
but this returned nothing.
Is this something that can be accomplished by cypher/neo4j or is this something that is best handled by returning all ingredients and sorted through them myself?
Bonus: Also is there a way to use cypher to match all values that a chef has to all values that a recipe requires. So far I've only returned all partial matches that are returned by a chef-[:has_value]->ingredient_value<-[:requires_value]-recipe and aggregating the results myself.
Update 01/10/2013:
Came across this in the Neo4j 2.0 reference:
Try not to use optional relationships.
Above all,
don’t use them like this:
MATCH a-[r?:LOVES]->() WHERE r IS NULL where you just make sure that they don’t exist.
Instead do this like so:
MATCH (a) WHERE NOT (a)-[:LOVES]->()
Using cypher for checking if relationship doesn't exist:
...
MATCH source-[r?:someType]-target
WHERE r is null
RETURN source
The ? mark makes the relationship optional.
OR
In neo4j 2 do:
...
OPTIONAL MATCH source-[r:someType]-target
WHERE r is null
RETURN source
Now you can check for non-existing (null) relationship.
For fetching nodes with not any relationship
This is the good option to check relationship is exist or not
MATCH (player)
WHERE NOT(player)-[:played]->()
RETURN player
You can also check multiple conditions for this
It will return all nodes, which not having "played" Or "notPlayed" Relationship.
MATCH (player)
WHERE NOT (player)-[:played|notPlayed]->()
RETURN player
To fetch nodes which not having any realtionship
MATCH (player)
WHERE NOT (player)-[r]-()
RETURN player
It will check node not having any incoming/outgoing relationship.
If you need "conditional exclude" semantic, you can achieve it this way.
As of neo4j 2.2.1, you can use OPTIONAL MATCH clause and filter out the unmatched(NULL) nodes.
It is also important to use WITH clause between the OPTIONAL MATCH and WHERE clauses, so that the first WHERE defines a condition for the optional match and the second WHERE behaves like a filter.
Assuming we have 2 types of nodes: Person and Communication. If I want to get all Persons which have never communicated by the telephone, but may have communicated other ways, I would make this query:
MATCH (p: Person)
OPTIONAL MATCH p--(c: Communication)
WHERE c.way = 'telephone'
WITH p, c
WHERE c IS NULL
RETURN p
The match pattern will match all Persons with their communications where c will be NULL for non-telephone Communications. Then the filter(WHERE after WITH) will filter out telephone Communications leaving all others.
References:
http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3
http://java.dzone.com/articles/new-neo4j-optional
I wrote a gist showing how this can be done quite naturally using Cypher 2.0
http://gist.neo4j.org/?9171581
The key point is to use optional match to available ingredients and then compare to filter for missing (null) ingredients or ingredients with the wrong value.
Note that the notion is declarative and doesn't need to describe an algorithm, you just write down what you need.
The last query should be:
START chef = node(..)
MATCH (chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
WHERE (ingredient)<-[:has_ingredient]-chef
RETURN ingredient
This pattern: (ingredient)<-[:has_ingredient*0..0]-chef
Is the reason it didn't return anything. *0..0 means that the length of the relationships must be zero, which means that ingredient and chef must be the same node, which they are not.
I completed this task using gremlin. I did
x=[]
g.idx('Chef')[[name:'chef1']].as('chef')
.out('has_ingredient').as('alreadyHas').aggregate(x).back('chef')
.out('has_value').as('values')
.in('requires_value').as('recipes')
.out('requires_ingredient').as('ingredients').except(x).path()
This returned the paths of all the missing ingredients. I was unable to formulate this in the cypher language, at least for version 1.7.
For new versions of Neo4j, you'll have this error:
MATCH (ingredient:Ingredient)
WHERE NOT (:Chef)-[:HAS_INGREDIENT]->(ingredient)
RETURN * LIMIT 100;
This feature is deprecated and will be removed in future versions.
Coercion of list to boolean is deprecated. Please consider using NOT isEmpty(...) instead.
To fix it:
MATCH (ingredient:Ingredient)
WHERE NOT EXISTS((:Chef)-[:HAS_INGREDIENT]->(ingredient))
RETURN * LIMIT 100;

How do I find disconnected nodes on neo4j with Cypher?

I am toying with neo4j and noticed that all Cypher queries need a starting point in the START clause.
I was wondering how can I find all disconnected nodes using Cypher ?
thanks
If all your nodes are indexed (e.g. via auto-indexing) you could use an index query as a start point and then find those nodes that have no outgoing relationships.
start n=node:node_auto_index("id:*")
match n-[r?]->m
where r is null
return n
Nowadays I would rather use:
start n=node:node_auto_index("id:*")
where not (n-->m)
return n
With Neo4j v3.0+ I just use;
MATCH (n)
WHERE NOT (n)--()
RETURN n
(or variations thereof). The query is reasonably fast.
I use something like this, but only when I'm using spring-data-neo4j:
start n = node:__types__(className="com.app.entity.Model")
// match, where...
return n
Hope that helps!
You can't. Graph global queries are not possible with todays Cypher.

Resources