Hi, Michael,

Thanks for the quick response!  And sorry about my own late reply: I had to
go to a meeting right after I sent the first post and have just gotten back
right now.

Interesting suggestion with using path expression and collection
predicates.  How would you include an optional path here?  Is there a way
to return the 4th circle, which won't match in the path?

I agree union is a clearer way to write it, especially when there are only
2 subsets.  However, I'm concerned about situations where one needs to
include more subsets, sometimes maybe 4 or 5 or more.  With compound
criteria, it's easier to read when all the conditions are in the where
clause -- to me at least.

What makes it harder for me is that I'm generating the Cypher queries
dynamically, based on a tiny query language that the user puts together
using a web UI (originally through a lot of NOT|AND|OR dropdowns but now
with a rich editor embellished with auto-complete).  So essentially the
query comes in the form of such-and-such-class-with-these-properties; it
gets compiled and then gets translated into Cypher after it passes
validation.

It's definitely a lot easier to translate that user query into a Cypher
that actually allows new identifiers in the predicate; a lot more work to
do the translation in terms of union -- maybe even more than what I might
spend implementing the identifier in the predicates in Cypher.

Does that make sense or would some examples with the more complex type of
queries help?

Cheers,
Kai


On Tue, Oct 28, 2014 at 6:54 PM, Michael Hunger <
[email protected]> wrote:

> You can also do number 3) because you actually don't need "s"
>
> match (c:circle) where (c.id=4) or ( (c)-->(:square{id:1}) ) return c
>
> Only #4 is trickier but still possible, only not so nice to read :)
>
> *I think union is still the better choice here as you combine 2 different
> use-cases:*
>
> match (c:circle)-->(s:square) where s.id < 4 return c,s
> union match (c:circle{id:4}) optional match (c)-->(s) return c,s;
>
> But you can use a path expression as a collection of paths, which you then
> can use in collection predicates (all, any, single, none) , filter,
> extract, reduce.
>
> match (c:circle)
> where any(p in (c)-->(:square) where last(nodes(p)).id <http://s.id/> <
> 4) return c
>
>
>
> On Wed, Oct 29, 2014 at 2:12 AM, Kai Chen <[email protected]> wrote:
>
>> Hi,
>>
>> I'm not sure if this is the right place to submit this.  I was going to
>> open an FR ticket on github but changed my mind because I thought maybe
>> it's better to have a discussion here first.
>>
>> I've run into a couple of places where being able to say something like
>>     match (n ....) /* criteria doesn't involve binding an identifier n2 */
>>     where n.prop > threshold or ( (n)-->(n2:label{qualifier:"value"}) and
>> n2.prop < threshold )
>> would make the query a lot easier to read.  I'm aware that, in the case
>> of 'OR', I could use a union after using 2 separate match clauses.  And
>> that's what I've been going along with, until now when I need to
>> dynamically translate a user query into Cypher.  Here using union can
>> become very complex, as the relationships can nest arbitrary levels deep.
>> But if we had a syntax that can bind new identifiers in predicates, it
>> would be very easy and, more importantly, very readable.
>>
>> I've prepared a few simple use cases below.  (See attached image of the
>> model)
>>
>> * Data Set
>>
>>   Below creates a set of 7 nodes consisting of 4 circles, 2 squares, and
>> 1 triangle.
>>   2 circles point to 2 squares, 1 circle point to the triangle, and
>> another circle is dangling.
>>
>> create (:circle{id:1})-[:uses]->(:square{id:1});
>> create (:circle{id:2})-[:uses]->(:square{id:2});
>> create (:circle{id:3})-[:uses]->(:triangle{id:3});
>> create (:circle{id:4});
>>
>> * Verification
>>
>> neo4j-sh (?)$ match (c:circle) optional match (c)-[r]->(n) return c,
>> labels(c), r, n, labels(n);
>>
>> +--------------------------------------------------------------------------+
>> | c              | labels(c)  | r          | n              | labels(n)
>>  |
>>
>> +--------------------------------------------------------------------------+
>> | Node[10]{id:1} | ["circle"] | :uses[7]{} | Node[11]{id:1} | ["square"]
>>   |
>> | Node[12]{id:2} | ["circle"] | :uses[8]{} | Node[13]{id:2} | ["square"]
>>   |
>> | Node[14]{id:3} | ["circle"] | :uses[9]{} | Node[15]{id:3} |
>> ["triangle"] |
>> | Node[16]{id:4} | ["circle"] | <null>     | <null>         | <null>
>>   |
>>
>> +--------------------------------------------------------------------------+
>>
>> * Queries
>>
>> 1) Circles that don't point to any Squares
>>     This is easy and can be supported with the current syntax.
>>
>> neo4j-sh (?)$ match (c:circle) where not (c)-->(:square) return c;
>>
>>
>> +----------------+
>> | c              |
>> +----------------+
>>     | Node[14]{id:3} |
>>     | Node[16]{id:4} |
>> +----------------+
>>
>> 2) Circles that don't point Square(1)
>>     This can also be accomplished using the current syntax.  So path is
>> already supported; the only thing missing is to bind an identifier which
>> would allow filtering with additional predicate expressions.
>>
>> neo4j-sh (?)$ match (c:circle) where not (c)-->(:square{id:1}) return c;
>> +----------------+
>> | c              |
>> +----------------+
>> | Node[12]{id:2} |
>> | Node[14]{id:3} |
>> | Node[16]{id:4} |
>> +----------------+
>>
>> 3) Circles that point to Square(1) or with id(4)
>>     Here it's starting to get hairy.  Union queries may also become
>> grossly inefficient if the result sets are large.  This is where
>> identifier-binding in predicates can help make query more efficient and
>> maybe easier to read also.
>>
>> neo4j-sh (?)$ match (c:circle{id:4}) return c
>> > union match (c:circle)-->(s:square{id:1}) return c;
>> +----------------+
>> | c              |
>> +----------------+
>> | Node[16]{id:4} |
>> | Node[10]{id:1} |
>> +----------------+
>>
>>     Would like to say
>>         match (c:circle) where (c.id=4) or ( (c)-->(s:square{id:1}) )
>> return c
>>
>> 4) (Circle, Square) where Circle is either id(4) or points to Squares
>> with id < 4
>>     This is where the union query is beginning to deteriorate in
>> comprehensibility.  One has to remember to use optional match.  And I don't
>> know what it would look like, if the optional match is 2 or 3 levels deep.
>> Now imagine this is a portion of a larger query, where the 'c' nodes are
>> found by matching in another pattern.  Using the union would require one to
>> duplicate that code in all the subsets.  Having more shared predicates
>> would have the same effect.
>>
>> neo4j-sh (?)$ match (c:circle)-->(s:square) where s.id < 4 return c,s
>> > union match (c:circle{id:4}) optional match (c)-->(s) return c,s;
>> +---------------------------------+
>> | c              | s              |
>> +---------------------------------+
>> | Node[10]{id:1} | Node[11]{id:1} |
>> | Node[12]{id:2} | Node[13]{id:2} |
>> | Node[16]{id:4} | <null>         |
>> +---------------------------------+
>>
>>
>> Hope that was clear.  And sorry for the long post.
>>
>> I also would be more than happy to help implement this if it's not too
>> difficult and someone can point me to the right place to start -- it'd be a
>> feature that I'd really use a lot.
>>
>> Cheers,
>> Kai
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Neo4j" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>  --
> You received this message because you are subscribed to a topic in the
> Google Groups "Neo4j" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/neo4j/N5k06664XYI/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Neo4j" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to