wow! I wasn't aware of 'unwind' keyword, perfect ! And backported to 2.0.4
:)
Thanks a lot Michael, really appreciate :)

Michael

Le 1 août 2014 à 10:56, Michael Hunger <michael.hun...@neotechnology.com> a
écrit :

You can sort on the client or use this at the end:

unwind cars as car
return car
order by car.name asc

Michael


On Fri, Aug 1, 2014 at 9:41 AM, Michael Azerhad <michael.azer...@gmail.com>
wrote:

> Hello Michael,
>
> Thanks for this really great detailed answer ! Like it :)
>
> However I have a question :
>
> I do really prefer the last way (at the very bottom) using cypher and
> expressions to lazily limit results.
> I wonder whether it's also possible to order by car's name (not only
> limiting) the whole final collection.
> Indeed, as far as I know, order by could not be applied on Collect
> aggregate function directly.
> We would have to use With before collecting.. but the case here is that I
> end up with a collection incrementally built, so I'm forced to order a
> collection.
> Obviously, I can't incrementally build ordered collection since order
> should be applied on the whole directly.
> Is there a trick I may ignore to achieve global ordering ?
>
> Thanks a lot again :),
>
> Michael
>
> Le 1 août 2014 à 07:03, Michael Hunger <michael.hun...@neotechnology.com>
> a écrit :
>
> Not sure if I'd use cypher for those data volumes.
>
> I think in this case some imperative code filling a set of cars might be
> more sensible (i.e. a server extension)
> And using a label for the Car-Degree. (Alternatively you could also use a
> SELL1, SELL2 rel-type for the degrees, and then check if it has SELL(n..4)
> as sell relationships, that would probably be fastest.
>
> Set<Node> getCars(Node person, int level) {
>     Label degree = DynamicLabel.label("Degree"+level);
>     for (Relationship knows = person.getRelationships(KNOWS)) {
>          Node friend = knows.getOtherNode(person);
>          for (Relationship sells :
> friend.getRelationships(SELLS,OUTGOING)) {
>               Node car = sells.getEndNode();
>               if (car.hasLabel(degree)) {
>                    cars.add(car);
>                    if (cars.size() > limit) return cars;
>               }
>          }
>     }
>     return cars;
> }
>
> Make sure to do real-sized load tests.
>
> Something I thought could work is incrementally building up the data.
>
> MATCH (loggedUser:Person{id: 123})-[:KNOWS]-(p1:Person)
> OPTIONAL MATCH (p1)-[:SELLS]->(c1:Car)
> WITH p1, collect(c1) as cars
> OPTIONAL MATCH (p1)-[:KNOWS]-(p2:Person)
> OPTIONAL MATCH (p2)-[:SELLS]->(c2:Car:Degree2)
> WITH p2, cars + collect(c2) as cars
> OPTIONAL MATCH (p2)-[:KNOWS]-(p3:Person)
> OPTIONAL MATCH (p3)-[:SELLS]->(c3:Car:Degree3)
> WITH p3, cars + collect(c3) as cars
> OPTIONAL MATCH (p3)-[:KNOWS]-(p4:Person)
> OPTIONAL MATCH (p4)-[:SELLS]->(c4:Car:Degree4)
> WITH cars + collect(c4) as cars
>
> If you want to limit the cars, it would probably be more complicated.
>
> Something like this:
>
> MATCH (loggedUser:Person{id: 123})-[:KNOWS]-(p1:Person)
> OPTIONAL MATCH (p1)-[:SELLS]->(c1:Car)
> WITH p1, collect(c1)[0..{limit}] as cars
> OPTIONAL MATCH (p1)-[:KNOWS]-(p2:Person)
> OPTIONAL MATCH (p2)-[:SELLS]->(c2:Car:Degree2)
> WITH p2, case when length(cars) < {limit} then cars +
> collect(c2)[0..({limit}-length(cars))] else cars end  as cars
> OPTIONAL MATCH (p2)-[:KNOWS]-(p3:Person)
> OPTIONAL MATCH (p3)-[:SELLS]->(c3:Car:Degree3)
> WITH p3, case when length(cars) < {limit} then cars +
> collect(c3)[0..({limit}-length(cars))] else cars end as cars
> OPTIONAL MATCH (p3)-[:KNOWS]-(p4:Person)
> OPTIONAL MATCH (p4)-[:SELLS]->(c4:Car:Degree4)
> RETURN case when length(cars) < {limit} then cars +
> collect(c4)[0..({limit}-length(cars))] else cars end as cars
>
> it might even be more sensible to do the matches as expressions and only
> collect as few as you need.
>
> Like this:
>
> MATCH (loggedUser:Person{id: 123})-[:KNOWS]-(p1:Person)
> // iterate over all paths in the collection, extracting only the last node
> // but only taking the first 0..{limit} ones lazily from that collection
> WITH p1, [path in (p1)-[:SELLS]->(:Car) | last(path)][0..{limit}]
> ...
>
>
> On Fri, Aug 1, 2014 at 4:28 AM, Michael Azerhad <michael.azer...@gmail.com
> > wrote:
>
>> Fix of my query above, I missed to specify the logged user node:
>>
>>
>> MATCH (d:Degree {id: 1})<-[:TARGET_TO]-(c:Car)<-[:SELLS]-(p:Person)-[
>> KNOWS]-(loggedUser:Person{id: 123})
>> RETURN c
>> UNION
>> MATCH (d:Degree {id: 2})<-[:TARGET_TO]-(c:Car)<-[:SELLS]-(p:Person)-[
>> KNOWS*..2]-(loggedUser:Person{id: 123})
>> RETURN c
>> UNION
>> MATCH (d:Degree {id: 3})<-[:TARGET_TO]-(c:Car)<-[:SELLS]-(p:Person)-[
>> KNOWS*..3]-(loggedUser:Person{id: 123})
>> RETURN c
>> UNION
>> MATCH (d:Degree {id: 4})<-[:TARGET_TO]-(c:Car)<-[:SELLS]-(p:Person)-[
>> KNOWS*..4]-(loggedUser:Person{id: 123})
>> RETURN c
>>
>> It's important :)
>>
>> On Friday, August 1, 2014 4:24:41 AM UTC+2, Michael Azerhad wrote:
>>>
>>> Hi,
>>>
>>> I really think about making the following scenario optimal using Cypher
>>> and Neo4j 2.X.X:
>>>
>>> Let's suppose this classic person knowledge pattern:
>>>
>>> (a:Person)-[:KNOWS]-(b:Person)
>>>
>>>
>>> Each person can sell his car by specifying its visibility according to
>>> the degree of separation of its choice.
>>> Example:
>>>
>>> Person A wants to sell a car.
>>> He expects people distant of 2 degrees maximum to "see" his sale
>>> announcement. (friends of friends maximum, including his direct friends)
>>>
>>> Therefore, when Person B logs on and click on "list all the sales", only
>>> sales that concerns him (according to the specified degree of separation by
>>> the seller previously).
>>>
>>> So if Person B is distant from Person A of 1 or 2 degrees (2 degrees
>>> being the degree effectively specified set by Person A, he could set degree
>>> 4 but it's an example), he can see the announcement.
>>> Otherwise, he can't see it.
>>>
>>> What would be the optimal cypher query to retrieve at once, all the sale
>>> announcements that concern the logged user.
>>>
>>> Firstly, I managed the case with this strategy:
>>> _ Storing the expected degree for visibility in the Car node => Ferrari
>>> (id:..., degreeFilter: 2)
>>> _ A cypher query that traverse every cars, pick the number and compare
>>> it to the length of the result of *shortestPath* cypher function
>>> applies to Person(A)-[:KNOWS*....4]-Person(B).   (4 being the maximum
>>> degree possible, set by any seller)
>>> If the length is superior to the degreeFilter, then the user would *not*
>>> be able to see this concerned announcement.
>>>
>>> Main drawback of this strategy:  I have to open EVERY car node to check
>>> for this degreeFilter property...
>>> If I have 160 000 000 of car nodes, I easily imagine the impact on query
>>> performance.
>>>
>>> So I think a little about alternatives strategy and really think about
>>> this one.
>>> Since I limit the maximum degreeFilter being set to 4 (a little and
>>> finite number), why not extract the degreeFilter property to a "Degree"
>>> node, and make 4 queries with UNION like this:
>>>
>>> MATCH (d:Degree {id: 1})<-[:TARGET_TO]-(c:Car)<-[:SELLS]-(p:Person)-[
>>> KNOWS]-(p2:Person)
>>> RETURN c
>>> UNION
>>> MATCH (d:Degree {id: 2})<-[: TARGET_TO]-(c:Car)<-[:SELLS]-(p:Person)-[
>>> KNOWS*..2]-(p2:Person)
>>> RETURN c
>>> UNION
>>> MATCH (d:Degree {id: 3})<-[: TARGET_TO]-(c:Car)<-[:SELLS]-(p:Person)-[
>>> KNOWS*..3]-(p2:Person)
>>> RETURN c
>>> UNION
>>> MATCH (d:Degree {id: 4})<-[: TARGET_TO]-(c:Car)<-[:SELLS]-(p:Person)-[
>>> KNOWS*..4]-(p2:Person)
>>> RETURN c
>>>
>>>
>>> There wouldn't be any duplicates, therefore no need to use UNION ALL but
>>> UNION.
>>>
>>> However, I just read that post-processing on the whole joined result set
>>> is not an actual feature in Neo4j 2.X.X.
>>>
>>> Indeed,* what if I would like to paginate sale announcements.*
>>> The basic ideal way would be to just add :  SKIP/LIMIT 10 (it's an
>>> example, not the real syntax) at the end of those 4 queries...
>>> But it would be only apply to the last, not the whole...
>>>
>>> So to sum up:
>>>
>>>
>>>    1. Is my query optimal if I use UNION or a better alternative exists
>>>    regarding this specific scenario ?
>>>    2. If UNION is the best solution, how to handle some kind of
>>>    post-processing, like ordering all the unified announcements by car's 
>>> name.
>>>
>>> Thanks a lot for any potential answers :)
>>> I spent some times on it since it's interesting and I really want to
>>> find an optimal query, allowing to deal with millions of sales :)
>>>
>>>
>>> Michael
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>  --
>> 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 neo4j+unsubscr...@googlegroups.com.
>> 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/3vH1kaNC6a8/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> neo4j+unsubscr...@googlegroups.com.
>
> 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 neo4j+unsubscr...@googlegroups.com.
> 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/3vH1kaNC6a8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
neo4j+unsubscr...@googlegroups.com.
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 neo4j+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to