how to perform neo4j cypher code formatting - neo4j

Is there a way/website/sublime plugin etc, to format cypher code (make it align and tidy)?
Same as this site is doing for javascript for example:
http://jsbeautifier.org/

While not perfect, here is what I have been doing. (hopefully others will jump in and improve it)
var Cypher = document.body.innerText
Cypher = Cypher.replace(/(?:\s*(OPTIONAL MATCH|MATCH|WHERE|WITH|RETURN|DETACH DELETE|DELETE|UNWIND|CASE)\s*)/gi, function(match) {
return '\n' + match.toUpperCase() + ' '
});
Cypher = Cypher.replace(/(?:\s*(AND|NOT|DISTINCT)\s*)/gi, function(match) {
return ' ' + match.toUpperCase().trim() + ' '
});
Cypher = Cypher.replace(/(?:\s*(\w+)\(\s*)/gi, function(match) {
return ' ' + match.toUpperCase().trim()
});
document.body.innerText = Cypher
match (n), (n)--(m) where n.car=1 and not n.id="rawr" with n.name return collect(n) as cars
(JSFiddle version)

Related

Understanding Operators of Neo4j

String query = "START n1=node:TEST_INDEX(nodeName='" + elementID
+ "') match n1-[:hasSubClass]->n2-[:hasPropertyGroup]->n3-[:containsProperty]->n4 with n2 match n2-[:hasInstance]->n5 "
+ "where n2.elementType='class' and not(n4.status! = 'Deleted') and n4.nodeName! =~ '(?i)" + propertyName + "' and where count(n5)=0 return n4,count(n5)";
I am trying to convert this particular query to MATCH query facing issue in understanding these conditions
not(n4.status! = 'Deleted') and n4.nodeName! =~ '(?i)" + propertyName
+ "'
I tried to change the query :-
MATCH(n1:TESTDATA{nodeName:'ProductConcept'})
match (n1)-[:hasSubClass]->(n2)-[:hasPropertyGroup]->(n3)-[:containsProperty]->(n4) with n2,n4
match (n2)-[:hasInstance]->(n5)
where n2.elementType='class'
and NOT EXISTS(n4.status)
and n4.nodeName <>'(?i)view'
//and where count(n5)=0
return n4,count(n5)
Assuming you pass elementId and propertyName as parameters, this Cypher seems to be equivalent to the intent of your original query:
START n1=node:TEST_INDEX(nodeName=$elementId)
MATCH (n1)-[:hasSubClass]->(n2)-[:hasPropertyGroup]->()-[:containsProperty]->(n4)
WHERE
n2.elementType = 'class' AND
n4.status = 'Deleted' AND
(NOT n4.nodeName =~ ('(?i)' + $propertyName)) AND
SIZE((n2)-[:hasInstance]->()) = 0
RETURN n4
This query does not bother to return the equivalent of COUNT(n5), since the query requires that the value must always be 0.

How to express logical OR in property value?

MATCH (s:Product {id:'5001207'})-[r]-> (o) WHERE (o:ProdAttrs) AND any(key in keys(o) WHERE toLower(key) contains 'Network') return o
In this query, if I want to express "contains Network|Phone|Smart", how to modify the query? That is the logic 'OR' in value.
Edited:
I tested this but it doesn't work:
MATCH (s:Product {id:'5001207'})-[r]-> (o)
WHERE (o:Attrs OR o:ExAttrs) AND any(key in keys(o)
WHERE key =~ '(?!).*(network|phone).*')
return o
The non-RE version works. Any errors? There is no syntax error. It just doesn't return result as expected from the .
EDIT 2:
My function to generate the query:
public String query_partial_match(String skuid, List<String> attrKey) {
return "MATCH (s:Product {id:'" + skuid + "'})-[r]-> (o) " +
"WHERE " +
"(o:ExAttrs OR o:ProdAttrs) AND " +
"any(key in keys(o) WHERE key =~'(?i).*(" + attrKey + ").*') " +
"return o";
}
This is my Java method to generate the query. So how to use the Java list 'attrKey' in this query?
Just use OR in your WHERE clause. Might be helpful to work with the list of all lowercase props.
MATCH (s:Product {id:'5001207'})-[r]->(o:ProdAttrs)
WHERE any(key in [prop in keys(o) | toLower(prop)] WHERE key contains 'network' OR key contains 'phone' OR key contains 'smart')
RETURN o
One option is to use a regular expression to test for multiple alternate string values.
MATCH (s:Product {id:'5001207'})-->(o:ProdAttrs)
WHERE ANY(key in KEYS(o) WHERE key =~ '(?i).*(Network|Phone|Smart).*')
RETURN o;
(?i) enables case-insensitivity.
Also, if you pass in a parameter (say, $terms) containing the collection of target strings (e.g., ['Network', 'Phone', 'Smart']), the query can generate the corresponding regular expression. For example:
MATCH (s:Product {id:'5001207'})-->(o:ProdAttrs)
WHERE ANY(key in KEYS(o) WHERE
key =~ '(?i).*(' + REDUCE(s=$terms[0], t IN $terms[1..] | s + '|' + t) + ').*')
RETURN o;

Getting alphanumeric reference of nodes in py2neo, when looking for paths

I have a graph that consists of DATASET and GRAPH nodes. With the following relationships:
DATASET->READS->GRAPH
GRAPH->WRITES->DATASET
When I run the following : MATCH (p1:DATASET_NAME { name:'test1.dat' }),(p3:DATASET_NAME { name:'test32.txt' }), p = ((p1)-[:READS|:WRITES*1..8]->(p3))
RETURN p
In Neo4J Desktop I get a result that is correct, where node names are present. But when I run it in py2neo:
graph.run("MATCH (p1:DATASET_NAME {
name:'test1.dat' }),(p3:DATASET_NAME { name:'test32.txt' }), p = ((p1)-[:READS|:WRITES*1..8]->(p3)) RETURN p").dump()
I get a result in the following format:
(f3ff862)-[:READS]->(c539bdc)-[:WRITES]->(b217f5a)-[:READS]->(ebf9c4f)-[:WRITES]->(f9ddd22)-[:READS]->(fcca016)-[:WRITES]->(a9c241a)
(f3ff862)-[:READS]->(c539bdc)-[:WRITES]->(b217f5a)-[:READS]->(ebf9c4f)-[:WRITES]->(f9ddd22)-[:READS]->(fcca016)-[:WRITES]->(e152f69)-[:READS]->(fcca016)-[:WRITES]->(a9c241a)
(f3ff862)-[:READS]->(c539bdc)-[:WRITES]->(b217f5a)-[:READS]->(ebf9c4f)-[:WRITES]->(cbc5d42)-[:READS]->(fcca016)-[:WRITES]->(a9c241a)
I am assuming that these are some sort of references. Is there a way where I can get the string value for name from these references?
You are returning the matched path so what you see in py2neo is the representation of the path object. In the neo4j console it does a little extra looking up for you and presents the path as a set of nodes and relationships and it labels them according to what you have configured in the console.
If you want to see the names in your py2neo output you could use the reduce function on the returned path p to produce a string with the node names and relationship types. Something like this should get you started.
MATCH (p1:DATASET_NAME { name:'test1.dat' }),(p3:DATASET_NAME { name:'test32.txt' }), p = ((p1)-[:READS|:WRITES*1..8]->(p3))
RETURN head(nodes(p)).name + ' - ' + reduce(path_str = "", r in relationships(p) | path_str + type(r) + ' - ' + endnode(r).name)
In py2neo [Note the escape characters added in order to avoid cypher error. # ...reduce(path_str = \"\"... ]:
graph.run("MATCH (p1:DATASET_NAME { name:'/projects/bkrpty_vfcn/bkrpty_vfcn_vendr/data/serial/temp/yyyymmdd_yyyymmddhhmiss_bk_mrk_stat_init.dat' }),(p3:DATASET_NAME { name:'/projects/bkrpty_vfcn/bkrpty_vfcn_vendr/tables/onevgb1/ai_bkrpty_case' }), p = ((p1)-[:READS|:WRITES*1..8]->(p3)) RETURN head(nodes(p)).name + ' - ' + reduce(path_str = \"\", r in relationships(p) | path_str + type(r) + ' - ' + endnode(r).name)").dump()

Save just the relationship in neo4j

I am trying to persist just a relationship in Neo4j but doesn't work. See my query. My domain object has this relationship to itself.
#RelatedTo (type="PLUS_ME", direction = Direction.BOTH)
private Set<Errand> plusMe;
Then I run this query with a GraphRepository.
Errand e = new Errand ();
Errand e1 = new Errand ();
e = template.save(e);
e1 = template.save(e1);
p (e.getId() + " " + e1.getId ());
String query = "MATCH (one:Errand)" +
"WHERE one.id = " + e.getId() +
"MATCH (two:Errand)" +
"WHERE two.id = " + e1.getId() +
"CREATE (one)-[b:PLUS_ME]->(two)" +
"CREATE (two)-[a:PLUS_ME]->(one)";
eRepo.query(query, null);
But when I run this query with junit I get 0 as the size that is.
eRepo.findByPlusMe(e).size();
use parameters
you don't need the inverse relationship
are you sure your match statements returns the correct errands?
can you show the structure of your Errand class?
is your findByPlusMe repository query a annotated or derived query?

How do I get list of nodes from calculated shortest path?

My Cypher looks like this:
START source=node(16822), target=node(12449)
MATCH p = allShortestPaths(source-[*]-target)
return p
And I want to write equivalent C# code for this. This is what I've come up till now
var query = client.Cypher
.Start(new { source = sourceNode.Reference, target = targetNode.Reference })
.Match("p = allShortestPaths(source-[*]-target)")
.Return<Node<Data>>("x");
Where Data is the class which has a string property(string ID).
What should i put in place of x to get my result as a list of concatenated IDs which comprises the path.
Cypher 2.0
START source=node(16822), target=node(12449)
MATCH p = allShortestPaths(source-[*]-target)
return nodes(p)
Good old way of executing query was the last resort which i used
CypherQuery query1 = new CypherQuery(#"START m=node(" + sourceNode.Reference.Id.ToString() + "), n=node(" + targetNode.Reference.Id.ToString() + #")
match p = allshortestpaths(m-[*]-n)
return distinct Extract(x in NODES(p): x.NodeId) as paths", paramCollection, CypherResultMode.Set);
var paths = ((IRawGraphClient)client).ExecuteGetCypherResults<List<string>>(query1);

Resources