I have an user speaking several languages.
I am writing a query to find out if the user speaks english.
I want to find out if the user speaks english by searching if a relationship exists between the user node and and the language node.
I am doing this using rels.to_other or rels.to_others. Both are failing as described below. And BTW what is the difference between the "to_other" and "to_others" methods?
irb(main):105:0> u
=> #<User uuid: "b1461edd-a574-44a7-9555-68659a361be2", created_at: Tue, 06 Oct 2015 16:21:26 +0000, name: "Levi Damian", type: "Regular", updated_at: Tue, 06 Oct 2015 16:21:26 +0000>
irb(main):106:0> l
=> #<Language uuid: "e388eb70-66b2-4b20-8f15-6ca11b34d03d", name: "English">
irb(main):107:0> u.rels.to_other(l)
CYPHER 802ms MATCH n, (n)-[r]-(p) WHERE (ID(n) = {ID_n}) RETURN r as result | {:ID_n=>38}
NoMethodError: CYPHER 125ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
CYPHER 125ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>43}
CYPHER 125ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
CYPHER 124ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>42}
CYPHER 128ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
CYPHER 130ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>41}
CYPHER 124ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
CYPHER 125ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>86}
CYPHER 124ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>38}
CYPHER 129ms MATCH n WHERE (ID(n) = {ID_n}) RETURN n | {:ID_n=>87}
undefined method `to_other' for #<Array:0x007fedc2d6b980>
from (irb):107
from /Users/levi/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/railties-4.2.4/lib/rails/commands/console.rb:110:in `start'
Why this error and how I can make it work?
rels immediately returns all relationships from that node to... everything. It returns an array, hence the error. It can be an extremely slow, memory intensive operation if you have a node with many relationships.
Assuming you have a languages association in your model, you can do u.languages.match_to(l).exists? instead. It will return a boolean and does not return any graph objects. You can also use blank? or empty?.
Related
I am working on a query on the movie database to check the shortest paths between n nodes. In this simplified example, we want all the shortest paths between 2 movies:
match p=allShortestPaths((n)-[*]-(m)) where id(n) = 87 and id(m) = 121
return p;
Now I want to have all the shortest paths that don't include Keanu Reeves in it.
I tried this:
match p=allShortestPaths((n)-[*]-(m)) where id(n) = 87 and id(m) = 121 and NONE(n in nodes(p) where n.name = "Keanu Reeves")
return p;
This however takes an eternity to load, even after I have indexed the name field of Person...
Then In tried the following:
match p=allShortestPaths((n)-[*]-(m)) where id(n) = 87 and id(m) = 121
with p WHERE NONE(n in nodes(p) where n.name = "Keanu Reeves")
return p;
This however gives me no results. I misinterpreted this by thinking it would just return those paths which don't have Keanu Reeves in between:
(no changes, no records)
I tested if I could get only those with Keanu Reeves in between with the any() function. This works perfectly:
match p=allShortestPaths((n)-[*]-(m)) where id(n) = 87 and id(m) = 121
with p WHERE ANY(n in nodes(p) where n.name = "Keanu Reeves")
return p;
What is the best approach to tackle this? I must say that my production query is way more complex than this, but it all boils down to this problem. It has to be a performant solution.
The problem is that if one of the nodes from the path does not have the property name, then the entire check will not be passed.
So or do we check for the existence of a property:
match p=allShortestPaths((n)-[*]-(m))
where
n.title = 'The Replacements' and
m.title = 'Speed Racer' and
NONE(n in nodes(p) where EXISTS(n.name) and n.name = "Keanu Reeves")
return p
Or use the COALESCE function:
match p=allShortestPaths((n)-[*]-(m))
where
n.title = 'The Replacements' and
m.title = 'Speed Racer' and
NONE(n in nodes(p) where COALESCE(n.name, '') = "Keanu Reeves")
return p
I have ~1.5 M nodes in a graph, that are structured like this (picture)
I run a Cypher query that performs calculations on each relationship traversed:
WITH 1 AS startVal
MATCH x = (c:Currency)-[r:Arb*2]->(m)
WITH x, REDUCE(s = startVal, e IN r | s * e.rate) AS endVal, startVal
RETURN EXTRACT(n IN NODES(x) | n) as Exchanges,
extract ( e IN relationships(x) | startVal * e.rate) AS Rel,
endVal, endVal - startVal AS Profit
ORDER BY Profit DESC LIMIT 5
The problem is it returns the path ("One")->("hop")->("One"), which is useless for me.
How can I make it not choose the previously walked node as the next node (i.e. "One"->"hop"->"any_other_node_but_not_"one")?
I have read that NODE_RECENT should address my issue. However, there was no example on how to specify the length of recent nodes in RestAPI or APOC procedures.
Is there a Cypher query for my case?
Thank you.
P.S. I am extremely new (less than 2 month) to Neo4j and coding. So my apologies if there is an obvious simple solution.
I don't know if I understood your question completely, but I believe that you problem can be solved putting a WHERE clause on the MATCH to prevent the not desired relationship be matched, like this:
WITH 1 AS startVal
MATCH x = (c:Currency)-[r:Arb*2]->(m)
WHERE NOT (m)-[:Arb]->(c)
WITH x, REDUCE(s = startVal, e IN r | s * e.rate) AS endVal, startVal
RETURN EXTRACT(n IN NODES(x) | n) as Exchanges,
extract ( e IN relationships(x) | startVal * e.rate) AS Rel,
endVal, endVal - startVal AS Profit
ORDER BY Profit DESC LIMIT 5
Try inserting this clause after your MATCH clause, to filter out cases where c and m are the same:
WHERE c <> m
[EDITED]
That is:
WITH 1 AS startVal
MATCH x = (c:Currency)-[r:Arb*2]->(m)
WHERE c <> m
WITH x, REDUCE(s = startVal, e IN r | s * e.rate) AS endVal, startVal
RETURN EXTRACT(n IN NODES(x) | n) as Exchanges,
extract ( e IN relationships(x) | startVal * e.rate) AS Rel,
endVal, endVal - startVal AS Profit
ORDER BY Profit DESC LIMIT 5;
After using this query to create test data:
CREATE
(c:Currency {name: 'One'})-[:Arb {rate:1}]->(h:Account {name: 'hop'})-[:Arb {rate:2}]->(t:Currency {name: 'Two'}),
(t)-[:Arb {rate:3}]->(h)-[:Arb {rate:4}]->(c)
the above query produces these results:
+-----------------------------------------------------------------------------------------+
| Exchanges | Rel | endVal | Profit |
+-----------------------------------------------------------------------------------------+
| [Node[8]{name:"Two"},Node[7]{name:"hop"},Node[6]{name:"One"}] | [3,4] | 12 | 11 |
| [Node[6]{name:"One"},Node[7]{name:"hop"},Node[8]{name:"Two"}] | [1,2] | 2 | 1 |
+-----------------------------------------------------------------------------------------+
Neo4j Version: 3.0.4
Objective of the below query is to eliminate duplicate bus service and bustop in a path, it work fine if i didn't provide the relationship count -[r:CONNECTSWITH]-> but if the relationship count defined -[r:CONNECTSWITH*..3]-> ,then its throwing
Key not found: r
Working:
OPTIONAL MATCH p=(o:PORT{name:"busstop1"})-[r:CONNECTSWITH]->(d:PORT{name:"busstop2"})
WHERE ALL(r1 IN rels(p)
WHERE 1 = size(filter(r2 IN rels(p) WHERE (r1.service = r2.service))))
AND ALL(n IN nodes(p) WHERE 1 = size(filter(m IN nodes(p) WHERE id(m) = id(n))))
RETURN p
LIMIT 10
Not Working:
OPTIONAL MATCH p=(o:PORT{name:"busstop1"})-[r:CONNECTSWITH*..3]->(d:PORT{name:"busstop2"})
WHERE ALL(r1 IN rels(p)
WHERE 1 = size(filter(r2 IN rels(p) WHERE (r1.service = r2.service))))
AND ALL(n IN nodes(p) WHERE 1 = size(filter(m IN nodes(p) WHERE id(m) = id(n))))
RETURN p
LIMIT 10
Work around Solution:
OPTIONAL MATCH p=(o:PORT{name:"busstop1"})-[r:CONNECTSWITH*..3]->(d:PORT{name:"busstop2"})
WHERE ALL(r1 in rels(p)
WHERE 1 = size(filter(r2 IN rels(p) WHERE (r1.service = r2.service)))) =
ALL(n IN nodes(p) WHERE 1 = size(filter(m IN nodes(p) WHERE id(m) = id(n))))
AND ALL(r1 in rels(p)
WHERE 1 = size(filter(r2 IN rels(p) WHERE (r1.service = r2.service))))
RETURN p
LIMIT 10
Aside: This feels like a neo4j bug. If you are encountering this with the latest neo4j version, you may want to submit a neo4j issue.
As a possible workaround, since the query does not actually use the r identifier, try removing it from the query.
Here is my controller (index is sorted):
def index
if params[:limit]
#bisacs = Bisac.order(:bisac_code).page(params[:page]).per(params[:limit])
else
#bisacs = Bisac.order(:bisac_code).page(params[:page])
end
end
Here are the queries executed (too many in my opinion and too slow, 6-7 seconds for a first page or to navigate to he next / last one:
Started GET "/bisacs" for 127.0.0.1 at 2015-08-11 13:16:33 -0400
Processing by BisacsController#index as HTML
Rendered home/_main_links.html.erb (0.2ms)
CYPHER 358ms MATCH (result_bisac:`Bisac`) RETURN count(result_bisac) AS result_bisac
CYPHER 389ms MATCH (result_bisac:`Bisac`) RETURN result_bisac ORDER BY result_bisac.bisac_code SKIP {skip_0} LIMIT {limit_25} | {:skip_0=>0, :limit_25=>25}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319299}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319299}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320808}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320808}
CYPHER 120ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319262}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319262}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320349}
CYPHER 120ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320349}
CYPHER 120ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24318456}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24318456}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320054}
CYPHER 116ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320054}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321703}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321703}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319503}
CYPHER 117ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319503}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321755}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321755}
CYPHER 116ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319313}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319313}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321376}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321376}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321021}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321021}
CYPHER 123ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319280}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319280}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24318845}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24318845}
CYPHER 122ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320822}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320822}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24318841}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24318841}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321956}
CYPHER 117ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24321956}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319031}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319031}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320070}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320070}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24322195}
CYPHER 116ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24322195}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319124}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319124}
CYPHER 119ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24322258}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24322258}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24318767}
CYPHER 121ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24318767}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320583}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24320583}
CYPHER 118ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319086}
CYPHER 117ms MATCH n WHERE (ID(n) = {ID_n}) WITH n RETURN ID(n) | {:ID_n=>24319086}
Rendered bisacs/index.html.erb within layouts/application (6722.1ms)
Completed 200 OK in 7096ms (Views: 7095.5ms)
How this can be improved? Why these 25 nodes are fetched one by one?
To retrieve all 3983 codes in the Neo4j console takes only 1 second or so:
MATCH (result_bisac:`Bisac`) RETURN result_bisac ORDER BY result_bisac.bisac_code;
Returned 3983 rows in 1064 ms, displaying first 1000 rows.
Hrmm, ok, so this is another somewhat embarrassing answer ;)
If you put the following in your config (either in config/environments/development.rb or config/application.rb) it should fix it:
config.neo4j._active_record_destroyed_behavior = true
Explination: The gem implements the ActiveNode#exists? method a bit differently than the ActiveRecord#exists? method. In ActiveRecord it just does a check to see if the object was destroyed at some point in memory. In ActiveNode we were doing a check to the actual database (and maybe we need query caching at some point).
So, long story short, we didn't want to introduce this change right away because it's a breaking change, so I put in a configuration variable which fixes it for now. The configuration variable shouldn't be neccessary in version 6.0
I commented the following first 3 lines in the tag in the view and speed become acceptable, around one second:
<% #bisacs.each do |bisac| %>
<tr>
<td><%#= link_to 'Show', bisac %></td>
<td><%#= link_to 'Edit', edit_bisac_path(bisac) %></td>
<td><%#= link_to 'Destroy', bisac, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<td><%= bisac.bisac_code%></td>
<td><%= bisac.bisac_value%></td>
</tr>
<% end %>
However adding a link back to "show" makes the page rendering very slow again:
<% #bisacs.each do |bisac| %>
<tr>
<td><%= link_to bisac.bisac_code, bisac%></td>
<td><%= bisac.bisac_value%></td>
</tr>
<% end %>
I am using the following Neo4JClient code to query for all the shipment count that is due within a wee, one week to 21 days and greater than 21 days.
var query = GraphClient.Cypher
.Merge("(user:Person{InternalId:{userId}})")
.WithParam("userId", userId)
.With("user")
.Match("(veh:Vehicle)<-[:HAS_VEHICLE_TYPE]-(load:ActiveShipment)-[:SHIPPED_BY]->(shipper:Shipper), (user)-[:WORKS_FOR_COMPANY]->(transporter:Transporter)")
.Where("((load.RestrictedBidding = false) OR (user)-[:WORKS_FOR_COMPANY]->(transporter)<-[:HAS_TRANSPORTER]-(shipper)<-[:SHIPPED_BY]-(load))")
.AndWhere("(load)-[:HAS_VEHICLE_TYPE]->(veh)<-[:HAS_VEHICLE]-(transporter)")
.With("load, transporter, shipper, user")
.Match("p=(shipFrom:City)<-[:SHIP_FROM_CITY]-(load)-[:SHIP_TO_CITY]->(shipTo:City)")
.With("load, collect(shipFrom) as FromCities, collect(shipTo) as ToCities, COUNT(filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate <= {withinWeek})) as LessThanWeek , COUNT(filter(x IN Nodes(p) WHERE x:Shipment and (x.PickupDate > {withinWeek}) and (x.PickupDate <= {within3Week}))) as NextWeekToFortnight, COUNT(filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate > {within3Week})) as LaterThan3Week")
.WithParams(new { withinWeek = next7Days, within3Week = next3Weeks })
.Return((load,FromCities, ToCities, LessThanWeek , NextWeekToFortnight, LaterThan3Week )=>new
{
OneWeek = Return.As<long>("LessThanWeek"),
SevenToTwentyOneDays = Return.As<long>("NextWeekToFortnight"),
Later = Return.As<long>("LaterThan3Week")
});
this generates the following Cypher query
MERGE (user:Person{InternalId:2})
WITH user
MATCH (veh:Vehicle)<-[:HAS_VEHICLE_TYPE]-(load:ActiveShipment)-[:SHIPPED_BY]->(shipper:Shipper),
(user)-[:WORKS_FOR_COMPANY]->(transporter:Transporter) WHERE ((load.RestrictedBidding = false) OR (user)-[:WORKS_FOR_COMPANY]->(transporter)<-[:HAS_TRANSPORTER]-(shipper)<-[:SHIPPED_BY]-(load)) AND (load)-[:HAS_VEHICLE_TYPE]->(veh)<-[:HAS_VEHICLE]-(transporter)
WITH load, transporter, shipper, user
MATCH p=(shipFrom:City)<-[:SHIP_FROM_CITY]-(load)-[:SHIP_TO_CITY]->(shipTo:City)
WITH load, collect(shipFrom) as FromCities, collect(shipTo) as ToCities,
COUNT(filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate <= 4/30/2014 12:00:00 AM +05:30)) as LessThanWeek ,
COUNT(filter(x IN Nodes(p) WHERE x:Shipment and (x.PickupDate > 4/30/2014 12:00:00 AM +05:30) and (x.PickupDate <= 5/14/2014 12:00:00 AM +05:30))) as NextWeekToFortnight,
COUNT(filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate > 5/14/2014 12:00:00 AM +05:30)) as LaterThan3Week
RETURN LessThanWeek AS OneWeek , NextWeekToFortnight AS SevenToTwentyOneDays , LaterThan3Week AS Later
but the results are not what I expect as I am getting OneWeek , SevenToTwentyOneDays & Later all as 1.
To clarify what I am doing: I am trying to do is first get all the loads based on my selection criteria, and then want to get the counts of these loads based where they stand on the delivery dates and only return the count. SO the WITH is really needed in this query.
Q1: Is this even a valid query to write? and how can I fix it.
Q2: Will the use of filter like above impact my query performance and if yes Is there a simpler way to do this?
Edit:
BTW the Cypher query pasted above is from the Debug Text of neo4jClient which means the actual query is parameterized but the debug text is writing out the parameter values for easy understanding so the dates are not written properly.
Regards
Kiran
Q1: The date/time strings (e.g., "4/30/2014 12:00:00 AM +05:30") are not supported by Cypher. I suggest using epoch time (in milliseconds) -- presumably your nodes' date/time properties are using that?
Q2: This is a somewhat simpler (and probably faster) query. You had a lot of duplicated patterns, which have been removed. I was able to come up with a consolidated MATCH pattern. Also, I am proposing the use of parameters id, date1 and date2, which will allow the neo4j engine to cache the execution plan and re-use it with every query:
MERGE (user:Person{InternalId:{id}})
WITH user
MATCH (user)-[:WORKS_FOR_COMPANY]->(transporter:Transporter)-[:HAS_VEHICLE]->(veh:Vehicle)<-[:HAS_VEHICLE_TYPE]-(load:ActiveShipment)-[:SHIPPED_BY]->(shipper:Shipper)
WHERE ((load.RestrictedBidding = false) OR (transporter)<-[:HAS_TRANSPORTER]-(shipper)<-[:SHIPPED_BY]-(load))
WITH load, transporter, shipper, user
MATCH p=(shipFrom:City)<-[:SHIP_FROM_CITY]-(load)-[:SHIP_TO_CITY]->(shipTo:City)
WITH load, collect(shipFrom) as FromCities, collect(shipTo) as ToCities,
COUNT(filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate <= {date1})) as LessThanWeek ,
COUNT(filter(x IN Nodes(p) WHERE x:Shipment and (x.PickupDate > {date1}) and (x.PickupDate <= {date2}))) as NextWeekToFortnight,
COUNT(filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate > {date2})) as LaterThan3Week
RETURN LessThanWeek AS OneWeek , NextWeekToFortnight AS SevenToTwentyOneDays , LaterThan3Week AS Later;
Filter can reduce the size of a collection, possibly to zero, but it will still be one collection. Counting the collection(s) will return the number of collections, not the number of items in the collection. The number of collections will be the same (1 in your case) no matter what the filter does.
WITH [1,2] AS nn
RETURN COUNT (FILTER (n IN nn WHERE n > 0)) AS cnt;
==> +-----+
==> | cnt |
==> +-----+
==> | 1 |
==> +-----+
==> 1 row
==> 20 ms
If you change the filter criteria to n > 1 or n > 2 it still returns 1, because there is still one collection. If you expect the filter to change the result, you may be want to use length.
WITH [1,2] AS nn
RETURN LENGTH (FILTER (n IN nn WHERE n > 0)) AS cnt;
==> +-----+
==> | cnt |
==> +-----+
==> | 2 |
==> +-----+
==> 1 row
==> 20 ms
neo4j-sh (?)$
I don't quite understand your query so I don't know how to answer the rest. Particularly, a) which node has the date property? and b) Why are you testing for date property on all the nodes in path p? You can put sample data in a console to make it easier to answer.
Finally found what I was doing wrong.
This part of my code was incorrect.
WITH load, collect(shipFrom) as FromCities, collect(shipTo) as ToCities,
COUNT(filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate <= 4/30/2014 12:00:00 AM +05:30)) as LessThanWeek ,
COUNT(filter(x IN Nodes(p) WHERE x:Shipment and (x.PickupDate > 4/30/2014 12:00:00 AM +05:30) and (x.PickupDate <= 5/14/2014 12:00:00 AM +05:30))) as NextWeekToFortnight,
COUNT(filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate > 5/14/2014 12:00:00 AM +05:30)) as LaterThan3Week
RETURN LessThanWeek AS OneWeek , NextWeekToFortnight AS SevenToTwentyOneDays , LaterThan3Week AS Later
Instead what I needed was something like this:
WITH load, collect(shipFrom) as FromCities, collect(shipTo) as ToCities,
filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate <= 4/30/2014 12:00:00 AM +05:30) as LessThanWeek ,
filter(x IN Nodes(p) WHERE x:Shipment and (x.PickupDate > 4/30/2014 12:00:00 AM +05:30) and (x.PickupDate <= 5/14/2014 12:00:00 AM +05:30)) as NextWeekToFortnight,
filter(x IN Nodes(p) WHERE x:Shipment and x.PickupDate > 5/14/2014 12:00:00 AM +05:30) as LaterThan3Week
RETURN
COUNT( DISTINCT LessThanWeek) AS OneWeek ,
COUNT( DISTINCT NextWeekToFortnight) AS SevenToTwentyOneDays ,
COUNT( DISTINCT LaterThan3Week) AS Later