neo4jrb / neo4j-core

A simple unified API that can access both the server and embedded Neo4j database. Used by the neo4j gem
MIT License
99 stars 80 forks source link

If a `where` is specified between two `match`es (including `optional_match`), there should be a break #255

Open cheerfulstoic opened 8 years ago

cheerfulstoic commented 8 years ago

It is important that where clauses go with their match clauses and the Ruby API should reflect this.

I'm wondering if maybe we should re-think the way that clauses group together automatically. Maybe it should only happen if the same clause is used a number of times in a row? I think it made sense for ActiveRecord / arel, but maybe not for Cypher.

dmlond commented 8 years ago

This is actually a bug. According to the official documentation a Where clause must be grouped with the specific match or optional match it relates to, before any other match or optional match. Currently, Something like

Neo4j::Session.query.match(file_version: :FileVersion).where('file_version.model_id IN {file_versions}').params(file_versions: @file_versions).optional_match('(file_version)-[generated_by:WasGeneratedBy]->(generating_activity:Activity)')

produces cypher

"MATCH (file_version:`FileVersion`) OPTIONAL MATCH (file_version)-[generated_by:WasGeneratedBy]->(generating_activity:Activity) WHERE (file_version.model_id IN {file_versions})"

but this is wrong, and produces wrong results. It should produce cypher:

"MATCH (file_version:`FileVersion`) WHERE (file_version.model_id IN {file_versions}) OPTIONAL MATCH (file_version)-[generated_by:WasGeneratedBy]->(generating_activity:Activity)"
cheerfulstoic commented 8 years ago

Yeah, this is definitely a problem.

@dmlond What would you think about a mode in which making Query clause chains like this just simply outputted clauses in the order that you specified them (aside from probably combining multiple match / where / etc... clauses which are directly in a row)?

Originally I was basing the query syntax off of ActiveRecord's and so I built it to automatically group clauses together and all in a certain order. But Cypher is different than SQL in this respect and I didn't understand that at the time.

dmlond commented 8 years ago

Yeah, its not like AR. You might organise each match/optional match onto a list, and push each where onto a list of where clauses attached to the last match in the list at the time the where is called. Then pull off each match with its where clauses from the beginning of the match list.