InverseFalcon
InverseFalcon

Reputation: 30417

Any way to whitelist or blacklist properties returned from a node?

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

Answers (2)

stdob--
stdob--

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

Frank Pavageau
Frank Pavageau

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

Related Questions