[Neo4j] Execute cypher query from shell on Linux

2014-08-01 Thread Alex winter
Hi
I installed database on Linux server via ssh.
I have a list query and I want to test the performance.
I can run the query from neo4j shell. But I want to write the result (time 
of running query )to text file because I have many query+want to compare it 
later.

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


Re: [Neo4j] Problem relates to relationship index,schema index

2014-08-01 Thread Alex winter
Thanks.
I found that: 
- there is timeout for batch inserter( but i didn't find any information 
about how to set time out for this)
- another problem is because my data is quite big and the storage is not 
enough for batch inserter use to insert.

Anyway, I have questions:
- As I found on Internet, we can't update data with batchinserter? Is this 
right?
(My situation is when I create a node I didn't have enough information for 
this node but after that I look up from other thing so I have more 
information for this node)
- in the example: 
docs.neo4j.org/chunked/stable/batchinsert-examples.html
"

Map properties = new HashMap<>();properties.put( "name", 
"Mattias" );long mattiasNode = inserter.createNode( properties, personLabel 
);properties.put( "name", "Chris" );long chrisNode = inserter.createNode( 
properties, personLabel );

"
I test this example and it is ok but I don't understand why you don't need 
create new instance of Properties, and inserter put only the last value? 
Could I do this for big hashmap?

Thanks in advance


On Thursday, July 31, 2014 4:49:40 PM UTC+2, Michael Hunger wrote:
>
> Seems that your store is not ok.
>
> Can you try to run the consistency checker on your store?
>
> Download Neo4j Enterprise, and see 
> http://www.markhneedham.com/blog/2014/01/22/neo4j-backup-store-copy-and-consistency-check
>
> You can run 
>
> java -cp 'lib/*:system/lib/*' org.neo4j.consistency.ConsistencyCheckTool 
> *data/graph.db*
>
>
>
>
> On Thu, Jul 31, 2014 at 3:36 PM, Alex winter  > wrote:
>
>> Thanks
>> But I didn't find data/log or data/graph.db/message.log.
>> I only see file message.log in the neo4j database directory.
>> When I run create index on command, I found that a new folder is created 
>> in schema/index/lucene.
>> And I found file "failure-message". And that is the content:
>> org.neo4j.kernel.impl.nioneo.store.InvalidRecordException: 
>> PropertyRecord[136728222] not in use
>> at 
>> org.neo4j.kernel.impl.nioneo.store.PropertyStore.getRecord(PropertyStore.java:423)
>> at 
>> org.neo4j.kernel.impl.nioneo.store.PropertyStore.getLightRecord(PropertyStore.java:289)
>> at 
>> org.neo4j.kernel.impl.nioneo.store.PropertyStore.getPropertyRecordChain(PropertyStore.java:728)
>> at 
>> org.neo4j.kernel.impl.nioneo.xa.NeoStoreIndexStoreView$PropertyBlockIterator.(NeoStoreIndexStoreView.java:286)
>> at 
>> org.neo4j.kernel.impl.nioneo.xa.NeoStoreIndexStoreView$3.iterator(NeoStoreIndexStoreView.java:221)
>> at 
>> org.neo4j.kernel.impl.nioneo.xa.NeoStoreIndexStoreView$1.read(NeoStoreIndexStoreView.java:89)
>> at 
>> org.neo4j.kernel.impl.nioneo.xa.NeoStoreIndexStoreView$1.read(NeoStoreIndexStoreView.java:80)
>> at 
>> org.neo4j.kernel.impl.nioneo.xa.NeoStoreIndexStoreView$NodeStoreScan.run(NeoStoreIndexStoreView.java:330)
>> at 
>> org.neo4j.kernel.impl.api.index.IndexPopulationJob.indexAllNodes(IndexPopulationJob.java:212)
>> at 
>> org.neo4j.kernel.impl.api.index.IndexPopulationJob.run(IndexPopulationJob.java:107)
>> at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
>> at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
>> at java.util.concurrent.FutureTask.run(Unknown Source)
>> at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
>> at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
>> at java.lang.Thread.run(Unknown Source)
>> Nul Nul..
>>
>> Do you know why I can't create index from this log file?
>> Thanks
>>
>>
>> On Wednesday, July 30, 2014 4:27:18 AM UTC+2, Michael Hunger wrote:
>>
>>> Legacy indexes can be listed in the neo4j-shell or in the 
>>> localhost:7474/webadmin  console with index --list (see help index)
>>> Schema indexes with :schema in the browser or "schema" in the shell
>>>
>>> Logs are in data/log/* or data/graph.db/messages.log
>>>
>>>
>>> On Tue, Jul 29, 2014 at 8:26 AM, Alex winter  
>>> wrote:
>>>

 Hi.
 I have some problem relates to index:

 - When I use the statement " create index on .. "  I got error: "

 "Index entered a FAILED state. Please see database logs."

 So what is a database logs in neo4j database? So I could know why I 
 can't create index.

 - When I imported data to neo4j, i setup the property: auto 
 relationship index is true. So I know that it is created or not?The same 
 question for other legacy index.

 Thanks



  -- 
 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+un...@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+u

Re: [Neo4j] Re: Returning items regarding the degree of separations between users.

2014-08-01 Thread Michael Hunger
Yep probably

Sent from mobile device

Am 01.08.2014 um 14:51 schrieb Michael Azerhad :

> I had to add the keyword DISTINCT in my return clause like this: 
> ...
> UNWIND cars as extractedCars
> RETURN DISTINCT(extractedCars) 
> 
> It took now about 150ms that is pretty fast. 
> Is DISTINCT the best strategy in this case to avoid duplicates? 
> 
> Michael
> 
> On Friday, August 1, 2014 2:26:19 PM UTC+2, Michael Azerhad wrote:
>> 
>> I guess I found the reason of the slowness:
>> 
>> If Person A is friend with B, and B is friend with C and C is friend with A 
>> (cyclic), then the query returns duplicated cars. 
>> I end up with 180 cars instead of 51 .. 
> 
> -- 
> 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 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.


[Neo4j] Re: Better docs please

2014-08-01 Thread Rodger


Anders:
Glad you like the suggestion. 

Dave:
That source code from the bubble is really useful. Thanks!
https://github.com/neo4j/neo4j/blob/2.1.2/community/embedded-examples/src/main/java/org/neo4j/examples/EmbeddedNeo4j.java


Interesting that Java dependencies are so complex, that we actually need an 
internet connected software, Maven, to resolve them. And java is so 
complex, that we
need an IDE such as Netbeans to manage it. Netbeans, being a complex 
software by itself. 
When I took the java course, many of the issues were not so much java, as 
they were 
how to use Netbeans. Often the best part of the course for me was being 
able to 
ask the instructor, "what's wrong here?".  

This is so different from when I first learned to program. When we did the 
exams, we wrote
programs from memory, longhand, in paper booklets. 

As I look back on when I learned other technologies, such as PLSQL, and 
ProC (Oracle queries 
from within a C program), a simple tutorial/example that worked, 
integrating the technology stack,
was one key for me to get going and out of first gear. 

I'm really big on clear and simple docs that communicate. 
In one of my very first blog posts, I touched on this:
http://rodgersnotes.wordpress.com/2010/05/24/foryoureyesonly/

And I've made jokes about bad docs:
http://rodgersnotes.wordpress.com/2012/01/15/joke-how-many-people-does-it-take-to-install-an-oracle-product/
:)

I do think that the better the docs, the bigger will be the adoption of 
NEO4J. 

Thanks for all your help through the learning curves!


On Saturday, July 26, 2014 9:11:57 PM UTC-5, Rodger wrote:
>
> Dear NEO4J documentation staff:
>
>
>

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


Re: [Neo4j] Re: Returning items regarding the degree of separations between users.

2014-08-01 Thread Michael Azerhad
I had to add the keyword DISTINCT in my return clause like this: 
...
UNWIND cars as extractedCars
RETURN DISTINCT(extractedCars) 

It took now about 150ms that is pretty fast. 
Is DISTINCT the best strategy in this case to avoid duplicates? 

Michael

On Friday, August 1, 2014 2:26:19 PM UTC+2, Michael Azerhad wrote:
>
> I guess I found the reason of the slowness:
>
> If Person A is friend with B, and B is friend with C and C is friend with 
> A (cyclic), then the query returns duplicated cars. 
> I end up with 180 cars instead of 51 .. 
>

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


Re: [Neo4j] Re: Returning items regarding the degree of separations between users.

2014-08-01 Thread Michael Azerhad
I guess I found the reason of the slowness:

If Person A is friend with B, and B is friend with C and C is friend with A 
(cyclic), then the query returns duplicated cars. 
I end up with 180 cars instead of 51 .. 

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


Re: [Neo4j] Do I have to split relations of a node into domains?

2014-08-01 Thread Mattias Persson
The two approaches are essentially them same, although in 2.1 the "meta
node" benefits are built into the store format.

If you're querying relationships that are in a minority group
(type+direction) there's a good benefit, but if you query relationships in
a majority group, i.e. the most common type+direction, the benefit is not
as good.


On Sun, Jul 20, 2014 at 1:46 AM, Frandro  wrote:

> In my case, as the edges of a node grow the performance becomes worse.
> My use case includes traversing all neighbor nodes and their neighbor
> nodes. But the problem is that their relations of two types are growing.
>
> I've read the following board.
>
> https://groups.google.com/forum/#!searchin/neo4j/performance/neo4j/g63fTmPM4GE/vdSy5whsWgoJ
>
> There's a comment that recommends creating a meta node to have the most
> edges of the node.
> Another one is saying the problem will be mitigated in Neo4j 2.1.
>
> Any helpful comments will be appreciated.
>
> --
> 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.
>



-- 
Mattias Persson
Neo4j Hacker at Neo Technology

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


Re: [Neo4j] Re: Returning items regarding the degree of separations between users.

2014-08-01 Thread Michael Azerhad
I tried one of the query you suggested: 

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 takes more than 2 seconds to execute :s
When I opened each node like I did before (evoked above), the query took 
150 ms. 
I have only 51 cars in the graph and 15 persons ... 
Would the collect function impact the performance? 

Thanks :)

Michael



On Friday, August 1, 2014 10:56:04 AM UTC+2, Michael Hunger wrote:
>
> 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  > 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 > > 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 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
>> // b

Re: [Neo4j] Re: Returning items regarding the degree of separations between users.

2014-08-01 Thread Michael Azerhad
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  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 
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 
> 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 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  > 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

Re: [Neo4j] Re: Returning items regarding the degree of separations between users.

2014-08-01 Thread Michael Hunger
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 
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 
> 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 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  > 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 choi

Re: [Neo4j] Re: Returning items regarding the degree of separations between users.

2014-08-01 Thread Michael Azerhad
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  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 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 
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