Reputation: 30417
Nodes returned in neo4j seem to be special, in that they output as JSON objects, and they don't appear at all if they're null.
An example: I have a :Person object, and they can have 0 or more :Friend relationships to another :Person.
Let's say that a :Person has the following properties: ID, firstName, lastName, sensitiveThing.
sensitiveThing is a property that might be used by our system, or could be personally accessible to the user themselves, but we don't want to return it to any other user.
If I want a query to give me back data of my friends, and friends of those friends, I might use a query like this
MATCH (me:User{ID:777})-[:Friend]-(friend:User)
WITH me, friend
OPTIONAL MATCH (friend)-[:Friend]-(foaf:User)
WHERE me <> foaf
RETURN friend.ID, friend.firstName, friend.lastName, COLLECT(foaf) AS FriendOfAFriend
While this lets me nicely bundle up friends of friends as JSON objects within a JSON array, and correctly emits an empty array if a friend doesn't have any other friends besides me, I don't want to return sensitiveThing with this query.
If I try to replace COLLECT(foaf) with a custom object only including fields I care about, like this:
COLLECT({ID:(foaf.ID), firstName:(foaf.firstName), lastName:(foaf.lastName)})
then I get what I want...until I hit the case where there are no friends of friends. When I was working with nodes before, the object wouldn't even be emitted. But now, I would get something like this returned to me:
[{ID: (null), firstName: (null), lastName: (null)}]
This is obviously not what I want.
Ideally, I'm looking for a way to return a node as before, but whitelist or blacklist properties I want to emit, so I can retain the correct null handling if the node is null (from an optional match)
If I can't have that, then I'd like a way to use a custom object, but not return the object at all if all its fields are null.
Any other workarounds or tips for dealing with optional matches are more than welcome.
Upvotes: 2
Views: 201
Reputation: 29167
You can use apoc.map.removeKeys
:
WITH {p1: 1, p2: 2, p3: 3, p4: 4} as node
CALL apoc.map.removeKeys( node, ['p2', 'p4'] ) YIELD value
RETURN value
Upvotes: 2
Reputation: 11735
I've never seen a way to whitelist or blacklist properties in the documentation.
However, you can return your custom object by chaining collect
with extract
:
MATCH (me:User{ID:777})-[:Friend]-(friend:User)
WITH me, friend
OPTIONAL MATCH (friend)-[:Friend]-(foaf:User)
WHERE me <> foaf
WITH friend, collect(foaf) AS FriendOfAFriend
RETURN friend.ID, friend.firstName, friend.lastName,
extract(foaf in FriendOfAFriend | {ID:(foaf.ID), firstName:(foaf.firstName), lastName:(foaf.lastName)}) AS FriendOfAFriend
collect
will return an empty list if there are no friends, extract
will keep it that way.
Upvotes: 1