cypher query to connect a where clause with the elements of an array

1,780 views
Skip to first unread message

divyanshu das

unread,
Nov 7, 2012, 3:43:58 PM11/7/12
to ne...@googlegroups.com
I have neo4j 1.6.1 and I am using php .

I have an array "arr" of a particular property "prop" of nodes.

I want to delete all nodes from neo4j having a certain relationship "rel" except for the nodes whose property "prop" is in the array "arr".

Can somebody help me out with this? 

Wes Freeman

unread,
Nov 7, 2012, 3:54:40 PM11/7/12
to ne...@googlegroups.com
You can't delete via Cypher with that version of Neo. 

If you want to just find them, you could do something like (I'm not entirely sure this worked back then, either--you might consider upgrading):

start n=node(*)
where n.prop in n.arr
return n;

Wes

--
 
 

Wes Freeman

unread,
Nov 7, 2012, 4:09:54 PM11/7/12
to ne...@googlegroups.com
I guess that's not exactly what you asked for... how about this:


start n=node(*) 
match n-[:rel]->() 
where has(n.arr) and not(n.prop in n.arr) 
return n;

divyanshu das

unread,
Nov 7, 2012, 4:12:51 PM11/7/12
to ne...@googlegroups.com
Hey, thanks for prompt replies. If I am correct, node(*) method is not available in 1.6.1. Any workaround  for this?

Wes Freeman

unread,
Nov 7, 2012, 4:16:08 PM11/7/12
to ne...@googlegroups.com
I guess you could use the reference node, and consider that in your match. Sorry, I'm new to Neo as of 1.8 for the most part.

Wes

--
 
 

divyanshu das

unread,
Nov 7, 2012, 4:18:53 PM11/7/12
to ne...@googlegroups.com
If I upgrade to 1.8, then I get the delete queries. Now, If I delete the nodes, will the node ids for other users remain unchanged or neo4j automatically reuses the deleted ids?

Wes Freeman

unread,
Nov 7, 2012, 4:26:29 PM11/7/12
to ne...@googlegroups.com
It isn't a good idea to depend on node ids for long term use (rather, use an email address or guid or similar unique id, with an index). Ids are reused after you restart the server, I think, if they were deleted.

Wes

--
 
 

divyanshu das

unread,
Nov 7, 2012, 4:36:49 PM11/7/12
to ne...@googlegroups.com
Is there any other way to delete nodes in 1.6.1 without using cypher queries?

Wes Freeman

unread,
Nov 7, 2012, 4:52:52 PM11/7/12
to ne...@googlegroups.com
Well, I think the REST delete commands existed in 1.6 if you're using server. If you're using embedded, you can do it like this:
http://docs.neo4j.org/chunked/stable/tutorials-java-embedded-hello-world.html#_remove_the_data

--
 
 

divyanshu das

unread,
Nov 8, 2012, 11:55:02 AM11/8/12
to ne...@googlegroups.com
@Freeman, The code that you gave works for array when it is in neo4j.

I have a separate php array that I am fetching from mysql.

I need to delete the nodes and relationships for nodes whose certain property matches the values stored in thee array.

Wes Freeman

unread,
Nov 8, 2012, 12:17:20 PM11/8/12
to ne...@googlegroups.com
You can also specify a literal array in cypher... not sure what you're using from PHP, but you can do something like this via REST:
{query:"start n=node(*) 
match n-[:rel]->() 
where not(n.prop in {phparr}) 
return n;", params:{phparr:[1,2,3]}}

--
 
 

divyanshu das

unread,
Nov 8, 2012, 12:25:25 PM11/8/12
to ne...@googlegroups.com
I am using cypher queries as mentioned in https://github.com/jadell/neo4jphp/wiki/Cypher-and-gremlin-queries

my phparray is $result_array, so will the query look like this?

$queryTemplate = "START n = node(*) MATCH n-[:rel]->() WHERE not(n.prop in {phparr}) Return n", params:{phparra:$result_array};

Wes Freeman

unread,
Nov 8, 2012, 12:39:35 PM11/8/12
to ne...@googlegroups.com
They have an example there with a parameter using the constructor...

$queryString = "start n=node(*) ".
    "match n-[:rel]->() ".
    "where not(n.prop in {phparr}) ".
    "return n";
$query = new Everyman\Neo4j\Cypher\Query($client, $queryString, array('phparr' => $result_array));
$result = $query->getResultSet();
I'm assuming it knows how to convert a php array to a json array, but maybe that's not a good assumption. If it doesn't, you might have to do something like http://php.net/manual/en/function.json-encode.php to convert your php array to a json non-associative array.


--
 
 

divyanshu das

unread,
Nov 8, 2012, 1:00:19 PM11/8/12
to ne...@googlegroups.com
hey thanks. I saw this example after I posted the last reply.

Now, when i run this query for a particular node "abc" it just returns the the node "abc" multiple times(i guess no. of nodes which are not in that array).

If I run the query with node(*), it fails at node 0. giving the message:- The property 'prop' does not exist on Node[0].

How do I skip checking at node 0.

divyanshu das

unread,
Nov 8, 2012, 1:07:03 PM11/8/12
to ne...@googlegroups.com
I modified to query like this:-

WHERE has(n,prop) AND not(n.prop in {phparr})

divyanshu das

unread,
Nov 8, 2012, 1:17:44 PM11/8/12
to ne...@googlegroups.com
It gave me this error after running for 10 mins,

Fatal error: Uncaught exception 'Everyman\Neo4j\Exception' with message 'Unable to execute query [100]: Headers: Array ( ) Body: Array ( ) ' in /var/www/new-ui/app/libs/Everyman/Neo4j/Command.php:117 Stack trace: #0 /var/www/new-ui/app/libs/Everyman/Neo4j/Command/ExecuteCypherQuery.php(85): Everyman\Neo4j\Command->throwException('Unable to execu...', 100, Array, Array) #1 /var/www/new-ui/app/libs/Everyman/Neo4j/Command.php(70): Everyman\Neo4j\Command\ExecuteCypherQuery->handleResult(100, Array, Array) #2 /var/www/new-ui/app/libs/Everyman/Neo4j/Client.php(602): Everyman\Neo4j\Command->execute() #3 /var/www/new-ui/app/libs/Everyman/Neo4j/Client.php(164): Everyman\Neo4j\Client->runCommand(Object(Everyman\Neo4j\Command\ExecuteCypherQuery)) #4 /var/www/new-ui/app/libs/Everyman/Neo4j/Cypher/Query.php(65): Everyman\Neo4j\Client->executeCypherQuery(Object(Everyman\Neo4j\Cypher\Query)) #5 /var/www/new-ui/app/services/users_service.php(106): Everyman\Neo4j\Cypher\Query->getResultSet() #6 /var/www/new-ui/app/controllers/users_contro in /var/www/new-ui/app/libs/Everyman/Neo4j/Command.php on line 117

David Montag

unread,
Nov 8, 2012, 1:31:15 PM11/8/12
to ne...@googlegroups.com
Just want to jump in here. The current workaround for deleting indexed nodes with Cypher requires you to know what indexes the node is indexed in, and for which property keys and values it is indexed. You can then delete the node, and then look it up in all indexes where it was previously indexed. This will not return any results, but it will trigger the necessary cleanup of the index.

David

--
 
 



--
Neo Technology, www.neotechnology.com
Skype: ddmontag

divyanshu das

unread,
Nov 8, 2012, 1:42:29 PM11/8/12
to ne...@googlegroups.com
thnx for pointing this out. But I did not quite understand it. Does this mean, that if I replace "return" by "delete" it wont delete the nodes?

However, right now, I  want to return those nodes first so that I can check if I am actually deleting the right node.

Wes Freeman

unread,
Nov 8, 2012, 2:03:04 PM11/8/12
to ne...@googlegroups.com
Put a "where has(n.prop)" in the query. Or where not(id(n) = 0), if that's the only one.

Wes

--
 
 

Wes Freeman

unread,
Nov 8, 2012, 2:51:10 PM11/8/12
to ne...@googlegroups.com
It will. David is just saying (in response to the question about how to delete in cypher, earlier in the thread) that if you have indexes on those nodes (do you?), you should query the indexes on the particular fields that are indexed so the indexes get cleaned up, afterward. You also need to delete the relationships connected to those nodes at the same time (else you'll get an error about not being able to delete nodes with relationships), so you might end up with something like "match n-[r?]-() ... delete n,r;"

I'm not sure what the PHP error is coming from--I'm not much of a PHP guy, myself. Is this a single command that's failing after 10 minutes, or are you iterating through some list of arrays and it's failing on one of the particular arrays?

--
 
 

divyanshu das

unread,
Nov 8, 2012, 3:19:18 PM11/8/12
to ne...@googlegroups.com
Yes, I do have indexes. 

this is the query I am using:- $queryTemplate = "START n = node(*) MATCH n-[:rel]->b WHERE has(n.prop) AND not(b.prop in {phparr}) RETURN b";
phparr is one single array.

Ideally this query should return all the list of nodes "b" , which has a "rel" relationship and b.prop is not an element of array.
But it gives the error I pasted earlier

If I use this query:- $queryTemplate = "START n = node(1239147) MATCH n-[:rel]->b WHERE (n.prop in {phparr}) RETURN b";

I get nodes with b.prop in the array.

But when I use this query with a "not" in where clause it gives no results. I have tried it with 10 nodes. everytime zero results.

My db has 6 million nodes, and 1645 have property "prop"

Wes Freeman

unread,
Nov 8, 2012, 3:25:00 PM11/8/12
to ne...@googlegroups.com
Your queries might be mixing up the "n" and "b" identifiers. I think you mean:
"has(b.prop) and not(b.prop in {phparr})"

Wes

--
 
 

divyanshu das

unread,
Nov 8, 2012, 3:29:33 PM11/8/12
to ne...@googlegroups.com
Correction:- 

db has 6 million nodes more than 2-3 millions have "prop" property. I need to delete all those nodes with "prop" property and "rel" relationship whose "prop" is not listed in phparr.

divyanshu das

unread,
Nov 8, 2012, 3:42:45 PM11/8/12
to ne...@googlegroups.com
the database is designed in a way that, if a node has "rel" relationship it'll have "prop" property too.

has(n.prop) is just to check if starting node has "prop" property.

divyanshu das

unread,
Nov 9, 2012, 6:11:52 AM11/9/12
to ne...@googlegroups.com
Ok. so finally the query the completed, and shows me the desired results if I specify node numbers. 

But it fails for node(8). I am assuming its some memory management issue. Right now, I dont have time to get into this. 

Can someone tell me, how do I pass an array or list as an argument for start node. Something like,

start n = node(array of nodes)
Since I am already passing an array, so it will be second array. Is paasing of two arrays allowed in the same query?

divyanshu das

unread,
Nov 9, 2012, 6:15:57 AM11/9/12
to ne...@googlegroups.com
correction:- it should be node(*)  not node(8)

Wes Freeman

unread,
Nov 9, 2012, 7:08:22 AM11/9/12
to ne...@googlegroups.com
Yes, you can pass in two arrays, you just name them different things in the parameters, like:

start n=node({arr_of_nodes}) where n.prop in {phparr} ...

Wes

--
 
 

Michael Hunger

unread,
Nov 9, 2012, 7:18:53 AM11/9/12
to ne...@googlegroups.com
You can use parameters for that

Either in java or REST

start n=node({ids}) return n

Pass an array with the ids a parameter "ids" to the query execution


Sent from mobile device
--
 
 

divyanshu das

unread,
Nov 10, 2012, 4:50:36 AM11/10/12
to ne...@googlegroups.com
this is the query I am trying to input to return the nodes indexed which have a particular property "prop". When I provide individual "prop" values, I get the desired results. But I need to pass an array of values. I am using neo4j 1.8 and neo4jphp library. Also, queries based node(*) give error after running for sometime. Although node(*) type queries work in neo4j-shell.

$queryTemplate = "START n = node:nodeindex('prop:{phparr}') return n";
$query = new Query($client, $queryTemplate, array('phparr'=> $result_array));
$neo_result = $query->getResultSet();

Error:-

I have tried these formats for query:-
node:nodeindex(prop = "{phparr}")    // No error but returns zero results
node:nodeindex(prop:'{phparr}')         // Gives the above error

Any help here?

Wes Freeman

unread,
Nov 10, 2012, 9:38:55 AM11/10/12
to ne...@googlegroups.com
Try node:nodeindex("prop:{phparr}")?

Wes

--
 
 

divyanshu das

unread,
Nov 10, 2012, 10:53:16 AM11/10/12
to ne...@googlegroups.com
no luck....
Parse error: syntax error, unexpected T_STRING in /var/www/new-ui/app/services/users_service.php on line 106


--
 
 

Wes Freeman

unread,
Nov 10, 2012, 11:01:04 AM11/10/12
to ne...@googlegroups.com
Just grasping here... one final attempt before I give up:

node:nodeindex(prop={phparr})


--
 
 

Wes Freeman

unread,
Nov 10, 2012, 11:02:18 AM11/10/12
to ne...@googlegroups.com
Now that I reread exactly what you're trying to do, I don't think it's going to work.

There's no way to do an "IN" query against an index, as far as I know.

divyanshu das

unread,
Nov 10, 2012, 11:08:27 AM11/10/12
to ne...@googlegroups.com
damn...!!

and queries for node(*) are not working.  i am stuck then.


--
 
 

divyanshu das

unread,
Nov 10, 2012, 1:27:17 PM11/10/12
to ne...@googlegroups.com
What is wrong in this query?

$queryTemplate = "START n = node(123) MATCH n-[r:rel]-b WHERE has(b.prop) AND not(b.prop in {phparr}) DELETE b, r";

I need to delete all nodes having a relationship "rel" with node 123, and "prop" not in the "phparr" array.

Andres Taylor

unread,
Nov 10, 2012, 2:04:56 PM11/10/12
to ne...@googlegroups.com
What makes you say that there is something wrong with your query?

Andrés

--
 
 



--
The best way to ask for Cypher help: http://console.neo4j.org/usage.html 

divyanshu das

unread,
Nov 10, 2012, 2:07:10 PM11/10/12
to ne...@googlegroups.com
because its giving me a error, its not deleting the nodes and relationships.

when I use RETURN, it reurns nodes.

but with DELETE, it doesnt delete them.

This is the error that I am getting:-

Fatal error: Uncaught exception 'Everyman\Neo4j\Exception' with message 'Unable to execute query [400]: Headers: Array ( [Content-Length] => 1351 [Content-Encoding] => UTF-8 [Content-Type] => application/json [Access-Control-Allow-Origin] => * [Server] => Jetty(6.1.25) ) Body: Array ( [message] => Unable to commit transaction [exception] => TransactionFailureException [stacktrace] => Array ( [0] => org.neo4j.kernel.TopLevelTransaction.finish(TopLevelTransaction.java:134) [1] => org.neo4j.cypher.internal.pipes.CommitPipe.createResults(CommitPipe.scala:45) [2] => org.neo4j.cypher.internal.executionplan.ExecutionPlanImpl$$anonfun$5$$anonfun$apply$3.apply(ExecutionPlanImpl.scala:104) [3] => org.neo4j.cypher.internal.executionplan.ExecutionPlanImpl$$anonfun$5$$anonfun$apply$3.apply(ExecutionPlanImpl.scala:104) [4] => org.neo4j.cypher.PipeExecutionResult.immutableResult(PipeExecutionResult.scala:37) [5] => org.ne in /var/www/new-ui/app/libs/Everyman/Neo4j/Command.php on line 117


--
 
 

divyanshu das

unread,
Nov 10, 2012, 5:18:29 PM11/10/12
to ne...@googlegroups.com
@andres,

So, there was nothing wrong in the cypher query.

I dont know why, but cypher delete query does not work for neo4jphp library.

This is how, I was able to delete:-

I used the RETURN statement, to get the Result Set.

->After that, parse that result set to get node ids and store them in an array.
->loop through the array, and for each element i.e. ID, $id(say)
   use getNode($id) to get the node,
->for these nodes, use getRelationships($id) to get the relationships. This returns a relationship array.
->loop through this array, use delete() to delete the relationships.
->Outside the relationship loop, use delete() for node to delete the node.

Hope that helps for someone else who is facing the same problem.





On Sunday, 11 November 2012 00:37:56 UTC+5:30, divyanshu das wrote:
because its giving me a error, its not deleting the nodes and relationships.

when I use RETURN, it reurns nodes.

but with DELETE, it doesnt delete them.

This is the error that I am getting:-

Fatal error: Uncaught exception 'Everyman\Neo4j\Exception' with message 'Unable to execute query [400]: Headers: Array ( [Content-Length] => 1351 [Content-Encoding] => UTF-8 [Content-Type] => application/json [Access-Control-Allow-Origin] => * [Server] => Jetty(6.1.25) ) Body: Array ( [message] => Unable to commit transaction [exception] => TransactionFailureException [stacktrace] => Array ( [0] => org.neo4j.kernel.TopLevelTransaction.finish(TopLevelTransaction.java:134) [1] => org.neo4j.cypher.internal.pipes.CommitPipe.createResults(CommitPipe.scala:45) [2] => org.neo4j.cypher.internal.executionplan.ExecutionPlanImpl$$anonfun$5$$anonfun$apply$3.apply(ExecutionPlanImpl.scala:104) [3] => org.neo4j.cypher.internal.executionplan.ExecutionPlanImpl$$anonfun$5$$anonfun$apply$3.apply(ExecutionPlanImpl.scala:104) [4] => org.neo4j.cypher.PipeExecutionResult.immutableResult(PipeExecutionResult.scala:37) [5] => org.ne in /var/www/new-ui/app/libs/Everyman/Neo4j/Command.php on line 117

Josh Adell

unread,
Nov 10, 2012, 8:43:20 PM11/10/12
to ne...@googlegroups.com
In the exception when you are using node(*) , it says: "Unable to execute query [100]: Headers: Array ( ) Body: Array ( ) '"
The fact that the REST request received no headers or body indicates that the request probably timed out while waiting for a response. 

I tried to recreate your scenario here: https://gist.github.com/4053297
but I don't have a database of 6 million nodes to check against. The delete worked successfully for the 1000 relationships the script creates.

Can you run the query successfully using CURL from the command line?

-- Josh

Josh Adell

unread,
Nov 10, 2012, 10:29:40 PM11/10/12
to ne...@googlegroups.com
I just tried with differing amounts of nodes being deleted. Around 700k, the query started timing out and throwing an exception.

-- Josh

divyanshu das

unread,
Nov 11, 2012, 4:58:42 AM11/11/12
to ne...@googlegroups.com
Sorry for late reply, I was sleeping(Time difference :P).

According to neo4j docs and as said by Michael Hunger, while using node(*), it loads the entire graph in memory probably what every database does.
Is there a way to increase the timeout time in neo4jphp library? The total size of my db is 29GB now.
It doesnot work even while using curl.

Josh Adell

unread,
Nov 11, 2012, 5:07:22 PM11/11/12
to ne...@googlegroups.com
Can you run it using curl, using the "--max-time=1200" option (this will keep the connection open for at most 20 minutes waiting for a response.)

I'm currently working on allowing setting of curl options in neo4jphp. But if you only need to run this command once, you can just do it from the command line, and pass curl the options directly.

-- Josh
Reply all
Reply to author
Forward
0 new messages