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
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.
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
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
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.
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] }