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 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