Parametrized like query in neo4j - neo4j

I want to create this query as parametrized query.
var query = ["Match (name:Name)-[r:IN_CLASS]->(class:Class)-[r1:HAS_STUDENTS]->(s:Student) where id(s)=",rollno," and lower(s.Name)=~'.*",name,".*' RETURN id(s),s.Name limit 5"].join('');
I have tried this code but it is giving error :
var query = ["Match (name:Name)-[r:IN_CLASS]->(class:Class)-[r1:HAS_STUDENTS]->(s:Student) where id(s)=",rollno," and lower(s.Name)=~'.*{name}.*' RETURN id(s),s.Name limit 5"].join('');
db.query(query , {name : name} , function(err,results){
if (err) return callback(err);
if(results){
return callback(null,results);
}
else{
return callback(null,false);
}
});
Please tell me where I am wrong?

You cannot have parameters that are part of a literal. You've tried
... WHERE ... lower(s.Name)=~'.*{name}.*'
Instead the whole regex expression needs to be the parameter value:
... WHERE ... lower(s.Name)=~ {name}
You need to concatenate your value with .* to .*<value>.* on the client side and pass this in as parameter value.
Edit:
You can also concatenate in Cypher:
... WHERE ... lower(s.Name)=~'.*'+{name}+'.*'
And for case insensitive regexps use:
... WHERE ... s.Name =~'(?i).*'+{name}+'.*'

Related

Cypher - Conditional SET

I'm trying to update a node in Neo4j, I'm passing variables to the query, and this variables could be null, and I don't want to update the node's property if the variable is null, so I tried this:
MATCH (n:address {id: $id})
SET n = {
name: COALESCE($name, n.name),
streetAddress: COALESCE($streetAddress, n.streetAddress),
build: COALESCE($build, n.build),
door: COALESCE($door, door),
latitude: COALESCE($latitude, n.latitude),
longitude: COALESCE($longitude, n.longitude)
}
RETURN (n)
But it gives the following error:
Neo4jError: Expected parameter(s): name, streetAddress, build, latitude, longitude
What can I do?
Because I'm using Javascript with the Neo4j driver for Node.js, I used string interpolation with a function to dynamically build the query:
verifyParam(param, paramName) {
if (param !== null && param !== undefined) return `SET n.${paramName} = ${param}`;
return '';
}
Then in the query string:
`
MATCH (n:address {id: $id})
${verifyParam($name, 'name')}
${verifyParam($streetAddress, 'streetAddress')}
${verifyParam($build, 'build')}
${verifyParam($door, 'door')}
${verifyParam($latitude, 'latitude')}
${verifyParam($longitude, 'longitude')}
RETURN (n)
`
Maybe is not the best solution, but I didn't found a better solution using only Cypher.

How to use parameter in neo4j cypher query

The Cypher official documentation seems to be inconsistent and misleading when it comes to assigning parameter values..we have the following examples in the refcard:
SET n.property1 = $value1
where value1 is a parameter defined
{
"value1": somevalue
}
However if you use this SET syntax you get an error value1 not defined. The correct syntax seems to be:
SET n.property1 = {value1}
also if its a MATCH query the parameter looks like this:
{
email: someemail
}
note no quotes around email
So if you have a MATCH and SET query with parameters you parameters definition looks like this:
{
email: someemail,
"status" : somestatus
}
Can someone explain this apparent inconsistency?
EDIT:
This is also an example from the neo4j docs:
using parameter with SET clause:
{
"surname" : "Taylor"
}
MATCH (n { name: 'Andres' })
SET n.surname = $surname
RETURN n
This returns surname undefined.
You can set params in neo4j desktop browser using :params.
For eg,
Execute, :params {surname: 'Taylor'}
Execute, MATCH (n { name: 'Andres' }) SET n.surname = $surname RETURN n
For more info of params, use :help params

Neo4j Cypher: String Build with Unwind and Array

Im using an unwind query in neo4j, with a nodejs driver (https://github.com/philippkueng/node-neo4j)
What I am trying to do is include an array of objects in the unwind query.
It currently works if I hard code the string as shown below, but i'm trying to have the array inserted dynamically.
UNWIND [{Label:'User',Lang:'English'},{Label:'Usuario',Lang:'Español'},{Label:'用户',Lang:'中文_简体'}] as ll
Regardless of the query I use, after testing, the above works, but if I do something like the following it doesn't:
var MyList = [{Label:'User',Lang:'English'},{Label:'Usuario',Lang:'Español'},{Label:'用户',Lang:'中文_简体'}];
"UNWIND "+ MyList " + as ll"
The problem is that when you do "UNWIND " + MyList you convert MyList to string, and it will be something like [object Object],[object Object],.... My first idea was to use JSON.stringify but that produces a JSON, which is not ok in cypher syntax (it is { "Label": ... } instead of { Label: ... }). The solution is to use parameters:
var queryString = 'UNWIND {list} as ll // continue query';
var queryParams = { list: MyList };
db.cypherQuery(queryString, queryParams, function(err, res) {
// handle response
});
Ideally you would use the ll identifier in your query.
However by seeing you have a property named Label, I remind you that currently it is not possible to add labels dynamically.
A possible query you might do is :
UNWIND MyList AS ll
CREATE (user:User) SET user.lang = {ll}.Lang
Chris

neo4jclient ill formed cypher request sent to server

Trying to execute the following cypher query (which executes ok from neoclipse)
START a=node(*) MATCH a-[:Knows]->p WHERE (p.Firstname! = "Steve" ) RETURN p
from neo4jclient with the following statement
protected void Populate()
{
var client = new GraphClient(new Uri("http://altdev:7474/db/data"));
client.Connect();
var query = client.Cypher
.Start(new RawCypherStartBit("all", "node(*)"))
.Match("all-[:Knows]->p")
.Where((Person p) => p.Firstname == "Steve")
.Return<Node<Person>>("Person");
var people = query.Results;
}
the client throws an exception, as follows
The query was: START all=node(*)
MATCH all-[:Knows]->p
WHERE (p.Firstname! = {p0})
RETURN Person
The response status was: 400 Bad Request
The response from Neo4j (which might include useful detail!) was: {
"message" : "Unknown identifier `Person`.",
"exception" : "SyntaxException",
"fullname" : "org.neo4j.cypher.SyntaxException",
"stacktrace" : [ "org.neo4j.cypher.internal.symbols.SymbolTable.evaluateType(SymbolTable.scala:59)", "org.neo4j.cypher.internal.commands.expressions.Identifier.evaluateType(Identifier.scala:47)", "org.neo4j.cypher.internal.commands.expressions.Expression.throwIfSymbolsMissing(Expression.scala:52)", "org.neo4j.cypher.internal.pipes.ColumnFilterPipe$$anonfun$throwIfSymbolsMissing$1.apply(ColumnFilterPipe.scala:61)", "org.neo4j.cypher.internal.pipes.ColumnFilterPipe$$anonfun$throwIfSymbolsMissing$1.apply(ColumnFilterPipe.scala:61)", "scala.collection.immutable.List.foreach(List.scala:309)", "org.neo4j.cypher.internal.pipes.ColumnFilterPipe.throwIfSymbolsMissing(ColumnFilterPipe.scala:61)", "org.neo4j.cypher.internal.pipes.PipeWithSource.<init>(Pipe.scala:63)", "org.neo4j.cypher.internal.pipes.ColumnFilterPipe.<init>(ColumnFilterPipe.scala:30)", "org.neo4j.cypher.internal.executionplan.builders.ColumnFilterBuilder.handleReturnClause(ColumnFilterBuilder.scala:60)", "org.neo4j.cypher.internal.executionplan.builders.ColumnFilterBuilder.apply(ColumnFilterBuilder.scala:38)", "org.neo4j.cypher.internal.executionplan.ExecutionPlanImpl.prepareExecutionPlan(ExecutionPlanImpl.scala:54)", "org.neo4j.cypher.internal.executionplan.ExecutionPlanImpl.<init>(ExecutionPlanImpl.scala:36)", "org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:80)", "org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:80)", "org.neo4j.cypher.internal.LRUCache.getOrElseUpdate(LRUCache.scala:37)", "org.neo4j.cypher.ExecutionEngine.prepare(ExecutionEngine.scala:80)", "org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:72)", "org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:76)", "org.neo4j.cypher.javacompat.ExecutionEngine.execute(ExecutionEngine.java:79)", "org.neo4j.server.rest.web.CypherService.cypher(CypherService.java:94)", "java.lang.reflect.Method.invoke(Method.java:616)", "org.neo4j.server.rest.security.SecurityFilter.doFilter(SecurityFilter.java:112)" ]
}
As you can see, essentially the queries are the same. And the nodes I'm trying to get are of _type "Person"
TIA
Marcelo
In your MATCH clause you use the identity p:
.Match("all-[:Knows]->p") // becomes MATCH all-[:Knows]->p
In your RETURN clause you change to using the identity Person:
.Return<Node<Person>>("Person"); // becomes RETURN person
You need to pick one and be consistent.
Integrating some other clean up too, your full query should be:
var query = client.Cypher
.Start(new { all = All.Nodes })
.Match("all-[:Knows]->p")
.Where((Person p) => p.Firstname == "Steve")
.Return<Person>("p");
It's down to the way you are creating the Cypher code, specifically what you are returning:
var query = client.Cypher
.Start(new RawCypherStartBit("all", "node(*)"))
.Match("all-[:Knows]->p")
.Where((Person p) => p.Firstname == "Steve")
.Return<Node<Person>>("p"); // <-- THIS LINE SHOULD SAY 'P' NOT 'Person'
The return statement requires the name to be the same as the node you have defined. So you use: all-[:knows]->p where you define p. Now you need to return it.
(Which is what Peter is saying in his answer :))
You are trying to return a Person node that is not assigned to anything in the query.

How do I use a in clause 'in' a grails.gorm.DetachedCriteria?

Is it possible to use an 'in' criteria in a Grails DetachedCriteria?
This is what I have,
def query = new DetachedCriteria(DomainObject)
// list is actually built up from another query,
// but for this example I will use a predefined list
query.where { 'in' 'id', [4L, 5L, 9L] }
def count = query.count()
What I am seeing is that the count, which you would expect to be 3, is actually just the entire DomainObject table.
How do I get this query to work?
Try assigning the result of where to a query:
query = query.where { 'in' 'id', [4L, 5L, 9L] }

Resources