1
votes

I have a following Cypher query:

MATCH (t:Tenant) WHERE ID(t) in {tenantIds} 
 OR t.isPublic 
WITH COLLECT(t) as tenants 
MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User) 
WHERE id(parentD) = {decisionId} 
 AND (not (parentD)-[:BELONGS_TO]-(:Tenant) 
   OR any(t in tenants WHERE (parentD)-[:BELONGS_TO]-(t))) 
 AND (not (childD)-[:BELONGS_TO]-(:Tenant) 
   OR any(t in tenants WHERE (childD)-[:BELONGS_TO]-(t)))  
MATCH (childD)<-[:SET_FOR]-(filterValue630:Value)-[:SET_ON]->(filterCharacteristic630:Characteristic) 
WHERE id(filterCharacteristic630) = 630 
WITH filterValue630, childD, ru, u 
WHERE  (filterValue630.value <= 799621200000)  
OPTIONAL MATCH (childD)<-[:SET_FOR]->(sortValue631:Value)-[:SET_ON]->(sortCharacteristic631:Characteristic) 
WHERE id(sortCharacteristic631) = 631 
RETURN ru, u, childD AS decision, 
[ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) 
 | {entityId: id(entity),  types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups, 
[ (parentD)<-[:DEFINED_BY]-(c1:Criterion)<-[:VOTED_ON]-(vg1:VoteGroup)-[:VOTED_FOR]->(childD) 
 | {criterionId: id(c1),  weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria, 
[ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[:SET_ON]-(v1:Value)-[:SET_FOR]->(childD) 
 | {characteristicId: id(ch1),  value: v1.value, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics 
ORDER BY sortValue631.value ASC, childD.createDate DESC 
SKIP 0 LIMIT 100

as a result of this query execution I receive 15 records where each of them correctly contains populated commentGroups, weightedCriteria and valuedCharacteristics collections.

But when I changing my query to the following one(I'm adding sort condition by criteria weight):

MATCH (t:Tenant) 
WHERE ID(t) in {tenantIds} 
 OR t.isPublic 
WITH COLLECT(t) as tenants 
MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User) 
WHERE id(parentD) = {decisionId} 
 AND (not (parentD)-[:BELONGS_TO]-(:Tenant) 
  OR any(t in tenants WHERE (parentD)-[:BELONGS_TO]-(t))) 
 AND (not (childD)-[:BELONGS_TO]-(:Tenant) 
  OR any(t in tenants WHERE (childD)-[:BELONGS_TO]-(t)))  
MATCH (childD)<-[:SET_FOR]-(filterValue630:Value)-[:SET_ON]->(filterCharacteristic630:Characteristic) 
WHERE id(filterCharacteristic630) = 630 
WITH filterValue630, childD, ru, u 
WHERE  (filterValue630.value <= 799621200000)  
OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) 
WHERE id(c) IN {criteriaIds} 
WITH c, childD, ru, u, (vg.avgVotesWeight * (CASE WHEN c IS NOT NULL THEN coalesce({criteriaCoefficients}[toString(id(c))], 1.0) ELSE 1.0 END)) as weight, vg.totalVotes as totalVotes 
OPTIONAL MATCH (childD)<-[:SET_FOR]->(sortValue631:Value)-[:SET_ON]->(sortCharacteristic631:Characteristic) 
WHERE id(sortCharacteristic631) = 631 
RETURN ru, u, childD AS decision, toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes, sortValue631, 
[ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) 
 | {entityId: id(entity),  types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups, 
[ (parentD)<-[:DEFINED_BY]-(c1:Criterion)<-[:VOTED_ON]-(vg1:VoteGroup)-[:VOTED_FOR]->(childD) 
 | {criterionId: id(c1),  weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria, 
[ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[:SET_ON]-(v1:Value)-[:SET_FOR]->(childD) 
 | {characteristicId: id(ch1),  value: v1.value, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics 
ORDER BY  weight DESC,  totalVotes ASC, sortValue631.value ASC, childD.createDate DESC 
SKIP 0 LIMIT 100

the query works without errors and returns the same result set of 15 records but commentGroups, weightedCriteria and valuedCharacteristics collections are only populated where weight > 0 The rest of them are null

This is wrong and not as expected. The commentGroups, weightedCriteria and valuedCharacteristics collections should be populated for all records in my result set as it was after the first query execution.

Right now I don't understand why the following part of new Cypher query prevents correct population of the mentioned collections:

OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) 
WHERE id(c) IN {criteriaIds} 
WITH c, childD, ru, u, (vg.avgVotesWeight * (CASE WHEN c IS NOT NULL THEN coalesce({criteriaCoefficients}[toString(id(c))], 1.0) ELSE 1.0 END)) as weight, vg.totalVotes as totalVotes 

What am I doing wrong within a new query and how to fix it?

UPDATED

This is the query which produces the issue:

MATCH (t:Tenant) WHERE ID(t) in [] 
  OR t.isPublic 
  WITH COLLECT(t) as tenants 
  MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User) 
  WHERE id(parentD) = 60565 
    AND (not (parentD)-[:BELONGS_TO]-(:Tenant) 
      OR any(t in tenants WHERE (parentD)-[:BELONGS_TO]-(t))) 
    AND (not (childD)-[:BELONGS_TO]-(:Tenant) 
      OR any(t in tenants WHERE (childD)-[:BELONGS_TO]-(t)))  
  MATCH (childD)<-[:SET_FOR]-(filterValue60639:Value)-[:SET_ON]->(filterCharacteristic60639:Characteristic) 
  WHERE id(filterCharacteristic60639) = 60639 
  WITH filterValue60639, childD, ru, u 
  WHERE  (filterValue60639.value <= 799621200000)  
  OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) 
  WHERE id(c) IN [60581, 60575] 
  WITH childD, ru, u, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes 
  OPTIONAL MATCH (childD)<-[:SET_FOR]->(sortValue60640:Value)-[:SET_ON]->(sortCharacteristic60640:Characteristic) 
  WHERE id(sortCharacteristic60640) = 60640 
  RETURN ru, u, childD AS decision, toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes, sortValue60640, 
  [ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) 
    | {entityId: id(entity),  types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups, 
  [ (parentD)<-[:DEFINED_BY]-(c1:Criterion)<-[:VOTED_ON]-(vg1:VoteGroup)-[:VOTED_FOR]->(childD) 
    | {criterionId: id(c1),  weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria, 
  [ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[:SET_ON]-(v1:Value)-[:SET_FOR]->(childD) 
    | {characteristicId: id(ch1),  value: v1.value, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics 
  ORDER BY  weight DESC,  totalVotes ASC, sortValue60640.value ASC, childD.createDate DESC 
  SKIP 0 LIMIT 100

for a some reason

  OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) 
  WHERE id(c) IN [60581, 60575] 

prevents commentGroups, weightedCriteria and valuedCharacteristics collection population for all childD that do not match this expression.. How to fix this ?

enter image description here

1
would be good if you can strip down the query further and provide a minimal dataset to demo it and share it via console.neo4j.org.Stefan Armbruster
I can't find information how to dump the database to Cypher script under Windows platform in order to be loaded to console.neo4j.orgalexanoid
@StefanArmbruster I have updated my question with a dump of my test database. Unfortunately I don't find a way how to upload it to console.neo4j.org so I have dumped my database to filesystem.alexanoid
I'm struggling with this query second day and don't understand how OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) WHERE id(c) IN [60581, 60575] impacts pattern comprehension like for example [ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[rso:SET_ON]-(v1:Value)-[rsf:SET_FOR]->(childD) | {characteristicId: id(ch1), value: v1.value, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics and how to fix it.alexanoid
Your db in the dump is password protected, and the default neo4j/neo4j isn't working.InverseFalcon

1 Answers

2
votes

Okay, this is a rather odd thing. I found something that should work, though at the moment I can't tell why it's working, just that it involves calculating weight and totalVotes before your return.

Take the first line of your RETURN, and replace it with this, which includes a WITH clause first, which will calculate the weight and totalVotes, then perform the RETURN:

WITH ru, u, childD, toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes, sortValue60640
RETURN ru, u, childD AS decision, weight, totalVotes, sortValue60640,

One other thing to note, you can save some unnecessary operations by performing your ORDER BY, SKIP, and LIMIT operations before you perform your pattern comprehensions:

WITH ru, u, childD, toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes, sortValue60640
ORDER BY  weight DESC,  totalVotes ASC, sortValue60640.value ASC, childD.createDate DESC 
  SKIP 0 LIMIT 100
RETURN ru, u, childD AS decision, weight, totalVotes, sortValue60640,
  [ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) 
    | {entityId: id(entity),  types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups, 
  [ (parentD)<-[:DEFINED_BY]-(c1:Criterion)<-[:VOTED_ON]-(vg1:VoteGroup)-[:VOTED_FOR]->(childD) 
    | {criterionId: id(c1),  weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria, 
  [ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[:SET_ON]-(v1:Value)-[:SET_FOR]->(childD) 
    | {characteristicId: id(ch1),  value: v1.value, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics