Change in Map Project Behavior

I noticed my tests started failing for a library I run based on map projections. I use the base Matrix data for my tests, and I have one for a map projection. Previously, referencing a property from a returned node in a map projection had no effect on the data returned for the node. Now, using that property in a projection will NULL out the property on the returned node.

Query:

MATCH (p:Person {name: 'Keanu Reeves'})-[actedIn:ACTED_IN]->(m:Movie)
OPTIONAL MATCH (m)<-[:ACTED_IN]-(p2:Person)
OPTIONAL MATCH (m)<-[:DIRECTED]-(d:Person)
WITH 
  p AS anchor, 
  actedIn, 
  m AS movie, 
  { 
    gKey: m.title,  
    actors: collect(DISTINCT p2{.*}), 
    directors: collect(DISTINCT d{.*}), 
    nested: { example: "data" }
  } AS staff
RETURN 
  anchor, 
  collect(actedIn) AS actingRels, 
  collect(movie) AS movies, 
  collect(staff) AS staff, 
  { gkey: anchor.name, feels: "so many"} AS feels, 
  1 AS surprise, 
  { one: "two", three: "four" } AS dictionary,
  { one: 1, two: 2.0, three: "four" } as objectionableDictionary

Returned data for anchor node:

{
  "identity": 1,
  "labels": [
    "Person"
  ],
  "properties": {
    "born": 1964,
    "name": null
  },
  "elementId": "4:56b3fd1b-6973-453f-9e00-0a833fb1fb1a:1"
}

Expected:

{
  "identity": 1,
  "labels": [
    "Person"
  ],
  "properties": {
    "born": 1964,
    "name": "Keanu Reeves"
  },
  "elementId": "4:56b3fd1b-6973-453f-9e00-0a833fb1fb1a:1"
}

Not sure if this is intentional. All other return values are as expected. Running on neo4j:5-enterprise

I don’t see anything in the code that would cause this. You are matching on his name, so the name property can’t be null.

Btw- I suggest using pattern comprehension instead of the optional matches. Executing these two sequentially results in a Cartesian product, which is the reason you need the distinct clause in your collect operations. The Cartesian product can cause performance issues with a large data set.

MATCH (p:Person {name: 'Keanu Reeves'})-[actedIn:ACTED_IN]->(m:Movie)
WITH 
  p AS anchor, 
  actedIn, 
  m AS movie, 
  { 
    gKey: m.title,  
    actors: [(m)<-[:ACTED_IN]-(p2:Person)|p2{.*}], 
    directors: [(m)<-[:DIRECTED]-(d:Person)|d{.*}], 
    nested: { example: "data" }
  } AS staff
RETURN 
  anchor, 
  collect(actedIn) AS actingRels, 
  collect(movie) AS movies, 
  collect(staff) AS staff, 
  { gkey: anchor.name, feels: "so many"} AS feels, 
  1 AS surprise, 
  { one: "two", three: "four" } AS dictionary,
  { one: 1, two: 2.0, three: "four" } as objectionableDictionary

Also, you could use the properties()method to get all of an entity’s properties instead of x{.*} I use map projection when creating a map from a subset of properties and/or adding other attributes.

While the syntax suggestions are helpful for performance, please test the code in the sample question on the movie graph as this is a question on a bug in cypher, not a request for approach improvements.

That's not to say I don't appreciate the answer and seeing a different approach. Testing YOUR query actually returns the expected result (after a syntax correction on the actors line where there's an extra closed paren).

Testing the query I posted still returns null for name on the anchor node.

Both should return the same results as per our mutual understanding of the language, and I assume how the devs intend it to work.

I did not see that behavior. What version are you using? I tested on 5.20. I can test with your version to verify.

Thanks for the check. I’m running it against the stated docker image which resolves to 5.21.0 as of this issue. The test suite I run for the lib has worked consistently in earlier versions. This particular test was implemented in February of 2023, so I think this is introduced in the latest version.