0
votes

I need to store large object graphs in the Neo4j database. Using Neo4jClient to talk to Neo4j. I decided to generate (using reflection) all the required CREATEs, etc. in a single query, and then perform an ExecuteWithoutResults. This to prevent writing code to create each individual object, and to boost performance by creating the entire graph with one database call.

My code is similar to this (but obviously more complicated):

ICypherFluentQuery query;
foreach(...) { query = query.CreateUnique(...); }
if (...) query = query.Match(...);
... etc. etc.

query.ExecuteWithoutResults();

The result is the lengthy query at the end of this post (this is the value of the query variable as produced by the Visual Studio debugger).

Problem is that when I check the Neo4j database after I've executed this, only the items created towards the start of the query are actually in the database (up to the first SupportingProgram). I confirmed that order has something to do with this by changing the generator so other CREATEs would come first - result was that the newly in front items now appeared in the database, while the newly in the back EmailAddress, etc. didn't appear.

Any feedback on why this problem occurs and possible work arounds would be greatly appreciated.

"START root=node(0)
MATCH root-[:HOSTS]->(n2)
WHERE n2.Key = 2552851c9015412ea808
WITH root,n2
CREATE UNIQUE (n2)-[:AGENCY_HAS_RESIDENTIAL_UNITS]->(n3)
CREATE (n3)-[:AGENCY_HAS_RESIDENTIAL_UNIT]->(n4 MyStory.Logic.CarerManagementSlice.Models.ResidentialUnit)
WITH root,n4
CREATE (n4)-[:RESIDENTIAL_UNIT_HAS_EMAIL_ADDRESS]->(n5 MyStory.Logic.Common.Models.EmailAddress)
WITH root,n4,n5
CREATE (n4)-[:RESIDENTIAL_UNIT_HAS_EMAIL_ADDRESS]->(n6 MyStory.Logic.Common.Models.EmailAddress)
WITH root,n4,n6
CREATE (n4)-[:RESIDENTIAL_UNIT_HAS_EMAIL_ADDRESS]->(n7 MyStory.Logic.Common.Models.EmailAddress)
WITH root,n4,n7
CREATE (n4)-[:RESIDENTIAL_UNIT_HAS_ADDRESS]->(n8 MyStory.Logic.CarerManagementSlice.Models.ResidentialUnitAddress)
WITH root,n4,n8
CREATE (n4)-[:RESIDENTIAL_UNIT_HAS_ADDRESS]->(n9 MyStory.Logic.CarerManagementSlice.Models.ResidentialUnitAddress)
WITH root,n4,n9
CREATE (n4)-[:RESIDENTIAL_UNIT_HAS_ADDRESS]->(n10 MyStory.Logic.CarerManagementSlice.Models.ResidentialUnitAddress)
WITH root,n4,n10
CREATE (n4)-[:RESIDENTIAL_UNIT_SUPPORTS_PROGRAM]->(n11 MyStory.Logic.CarerManagementSlice.Models.SupportingProgram)
WITH root,n4,n11
MATCH root-[:HOSTS]->(n12)
WHERE n12.Key = 2552851c9015412ea808
WITH root,n4,n11,n12
MATCH (n12)-[:CENTRE_BELONGS_TO]-(n13)
WITH root,n4,n11,n13
MATCH (n13)-[:HAS_PROGRAM]->(n14)
WHERE n14.UniqueId = 2
WITH root,n4,n11,n14
CREATE (n11)-[:SUPPORTING_PROGRAM_IS_LINKED_TO_PROGRAM]->(n14)
WITH root,n4,n11
CREATE (n4)-[:RESIDENTIAL_UNIT_SUPPORTS_PROGRAM]->(n15 MyStory.Logic.CarerManagementSlice.Models.SupportingProgram)
WITH root,n4,n15
MATCH root-[:HOSTS]->(n16)
WHERE n16.Key = 2552851c9015412ea808
WITH root,n4,n15,n16
MATCH (n16)-[:CENTRE_BELONGS_TO]-(n17)
WITH root,n4,n15,n17
MATCH (n17)-[:HAS_PROGRAM]->(n18)
WHERE n18.UniqueId = 2
WITH root,n4,n15,n18
CREATE (n15)-[:SUPPORTING_PROGRAM_IS_LINKED_TO_PROGRAM]->(n18)
WITH root,n4,n15
CREATE (n4)-[:RESIDENTIAL_UNIT_HAS_PHONE_NUMBER]->(n19 MyStory.Logic.Common.Models.PhoneNumberWithType)
WITH root,n4,n19
CREATE (n4)-[:RESIDENTIAL_UNIT_HAS_PHONE_NUMBER]->(n20 MyStory.Logic.Common.Models.PhoneNumberWithType)
WITH root,n4,n20
CREATE (n4)-[:RESIDENTIAL_UNIT_HAS_PHONE_NUMBER]->(n21 MyStory.Logic.Common.Models.PhoneNumberWithType)
WITH root,n4,n21
CREATE (n4)-[:HAS_RESIDENTIAL_UNIT_CLOSURE_REASON]->(n22 MyStory.Logic.CarerManagementSlice.Models.ResidentialUnitClosureReason)
WITH root,n4,n22
CREATE (n4)-[:HAS_RESIDENTIAL_UNIT_CLOSURE_REASON]->(n23 MyStory.Logic.CarerManagementSlice.Models.ResidentialUnitClosureReason)
WITH root,n4,n23
CREATE (n4)-[:HAS_RESIDENTIAL_UNIT_CLOSURE_REASON]->(n24 MyStory.Logic.CarerManagementSlice.Models.ResidentialUnitClosureReason)
WITH root,n4,n24"
1

1 Answers

1
votes

Could it just be that some of your matches fail, and so you don't get executions further on?

Probably you have to use MERGE for some of those?

Or replace them with optional matches and then handle the null values correctly?

What happens if you execute that statement in the Neo4j Browser or Shell? And when you execute fragments and actually return the results of your match-statements?

Also take care to use parameters whenever possible in your statements.

Personally I'd split up the creation in multiple statements but then execute them with a single http request.