Is it possible cypher dynamic label at #Query? - neo4j

I'm using SDN 3.1.0.RELEASE.
And i trying danamic label query like
#Query("MATCH (n:{0}) RETURN n")
public List<SimpleArticle> findAllByDomain(String domain);
and give String parameter like SimpleArticle.class.getSimpleName()
when i launched test code, i met "SyntaxException At {0}"
so i change query to
#Query("MATCH (n:`{0}`) RETURN n")
this code is work but don't find Domain node.
result log is "Executing remote cypher query: MATCH (n:`{0}`) RETURN n params {0=SimpleArticle}"
so i run this cypher query in query broswer
MATCH (n:`SimpleArticle`) RETURN n ;
It works and find node.
Can i use dynamic labels in #Query ?

Labels cannot be parameterized. The rationale for this is that different labels might result in different query plans. A parameterized query is always using the same query plan - therefore it's not possible.
The only way to use "semi"-dynamic labels is by using string concatenation or by Cypher DSL.

Related

Neo4j cypher queries returning different count result

I want a query that starting from a node, it counts the possible end nodes given relation type:
For example this query:
MATCH (start:typeA{my_id:"abc"})-[:rel]->(l:typeB) return count(l)
works great and returns a proper number, i.e., 500. The same happens with:
MATCH p=(start:BusStop{StopCode:"0247"})-[:CAN_BOARD]->(:Leg) return count(p)
However if I do:
MATCH (start:typeA{my_id:"abc"}) return count((start)-[:rel]->(:typeB))
returns 1.
What is the difference between this query and the previous ones?
The result of a path expression (as used in your last query) is a list of paths. This is different than the result when the same path pattern is used in a MATCH clause.
You would have gotten 500 if you changed your last query to use SIZE() instead of COUNT():
MATCH (start:typeA{my_id:"abc"}) return SIZE((start)-[:rel]->(:typeB))

Removing a node from the Cypher query result in Neo4j

I have the following cypher code:
MATCH (n)
WHERE toLower(n.name) STARTS WITH toLower('ja')
RETURN n
This case-insensitive query returns all the nodes which their names start with the substring "ja". For example if I execute this in my db it will return ["Javier", "Jacinto", "Jasper", "Jacob"]
I need this script to also remove the unwanted nodes on this list, for example let's say that an array containing ["Jasper, Javier"] is sent to the data access layer indicating that those two nodes shouldn't be returned, leaving the final query result as follows: ["Jacinto", "Jacob"]
How can I perform this?
If you know before making the query which items should be excluded you can say:
MATCH (n)
WHERE toLower(n.name) STARTS WITH toLower('ja')
AND NOT (toLower(n.name) IN ['jasper', 'javier'])
RETURN n

Like search on indexed properties is taking more time in cypher query of Neo4j

There is a relationship between Entity and Addess node. Entity has unique key constraint on eid and Address has unique key constraint on addressLocation.
I have millions of node for Entity and Address. Exact seach query works fine and here is the query -
match(e:Entity)-[r]->(a:Address) where a.addressLocation="ABC XYZ" return r
But like search query taking too much time that lead to ReadTimeOutException. Here is the query -
match(e:Entity)-[r]->(a:Address) where a.addressLocation=~".*(?i)ABC XYZ.*" return r
Can anybody tell me what i should do to get like search result as quick as exact search result.
The first query is using an index lookup (on Address.addressLocation):
match(e:Entity)-[r]->(a:Address) where a.addressLocation="ABC XYZ" return r
The second query is using a regular expression which is not able to use the index and is therefore not very performant:
match(e:Entity)-[r]->(a:Address) where a.addressLocation=~".*(?i)ABC XYZ.*" return r
Cypher has three string comparison operators STARTS WITH, ENDS WITH and CONTAINS. STARTS WITH will make use of an index so this query should be performant:
MATCH (e:Entity)-[r]->(a:Addres)
WHERE a.addressLocation STARTS WITH "ABC XYZ"
RETURN r
ENDS WITH and CONTAINS (which is really what you want) do not currently use an index, however in Neo4j 3.0 both will use an index. There is a milestone version of 3.0 available on the download page if you'd like to try it.

Create node and relationship given parent node

I am creating a word tree but when I execute this cypher query:
word = "MATCH {} MERGE {}-[:contains]->(w:WORD {{name:'{}'}}) RETURN w"
.format(parent_node, parent_node, locality[i])
where parent_node has a type Node
It throws this error:
py2neo.cypher.error.statement.InvalidSyntax: Can't create `n8823` with properties or labels here. It already exists in this context
formatted query looks like this:
'MATCH (n8823:HEAD {name:"sanjay"}) MERGE (n8823:HEAD {name:"sanjay"})-[:contains]->(w:WORD {name:\'colony\'}) RETURN w'
The formatted query is broken and won't work, but I also don't see how that could be what the formatted query actually looks like. When you do your string format you pass the same parameter (parent_node) twice so the final string should repeat whatever that parameter looks like. It doesn't, and instead has two different patterns for the match and merge clauses.
Your query should look something like
MATCH (n8823:Head {name: "sanjay"})
MERGE (n8823)-[:CONTAINS]->(w:Word {name: "colony"})
RETURN w
It's probably a bad idea to do string formatting on a Node object. Better to either use property values from your node object in a Cypher query to match the right node (and only the variable that you bind the matched node to in the merge clause) or use the methods of the node object to do the merge.
Although the MERGE clause is able to bind identifiers (like n8823), Cypher unfortunately does not allow MERGE to re-bind an identifier that had already been bound -- even if it would not actually change the binding. (On the other hand, the MATCH clause does allow "rebinding" to the same binding.) Simply re-using a bound identifier is OK, though.
So, the workaround is to change your Cypher query to re-use the bound identifier. Also, the recommended way to dynamically specify query data without changing the overall structure of a query is to use "query parameters". For py2neo, code along these lines should work for you (note that the parent_name variable would contain a name string, like "sanjay"):
from py2neo import Graph
graph = Graph()
cypher = graph.cypher
results = cypher.execute(
"MATCH (foo:{name:{a}}) MERGE (foo)-[:contains]->(w:WORD {{name:'{b}'}}) RETURN w",
a=parent_name, b=locality[i])

Optimizing Neo4j Cypher query matching on properties

I have a Cypher query that is performing extremely poorly (~ 30 sec):
START foo=node:foos('Name:*')
MATCH foo<-[:HasMember]-()<-[:PartOf]-()<-[:Connected]-bar
WHERE foo.Name IN ["name1", "name2"] AND bar.Enabled = true
RETURN DISTINCT bar.Guid AS Guid, foo.Name AS Name
What I think what is happening is that the Lucene index is used to pull out all values, and then graph search is used to match to the names in the set, because if I change the query to the one below it is orders of magnitude faster (16 ms):
START foo=node:foos('Name:"name1" OR Name:"name2"')
MATCH foo<-[:HasMember]-()<-[:PartOf]-()<-[:Connected]-bar
WHERE bar.Enabled = true
RETURN DISTINCT bar.Guid AS Guid, foo.Name AS Name
Is there a way to get the first query to execute as fast as the second without resorting to manually building a Lucene query out of the name set?
The other option would be to use a traversal but I prefer to stay in Cypher-land if possible.
Maybe if you don't want to build the query, try filtering earlier?
Like
START foo=node:foos('Name:*')
WHERE foo.Name IN ["name1", "name2"]
WITH foo
MATCH foo<-[:HasMember]-()<-[:PartOf]-()<-[:Connected]-bar
WHERE bar.Enabled = true
RETURN DISTINCT bar.Guid AS Guid, foo.Name AS Name

Resources