Hide properties from being returned by neo4j

I'm automatically adding system properties to nodes and edges which are only relevant to the system but shouldn't be returned to the user during a Cyper match query. These properties start with '$', so it would be possible to filter them by property name. However, I don't know the queries the user is going to execute, it could return a nodes, edges or some single values.

Is there a way to filter out certain properties by Neo4j? Would it be possible to implement an extension that intercepts only match queries and alters the result?

While you could build an extension to do this, you should use fine-grained access controls instead:

In this case, what you should do is specify access control rules that the $ properties are only accessible by the admin role (for example) so that readers can see anything they want, but can't retrieve the $ properties.

This would be by far the easiest & most extensible way to do this - but it relies on an enterprise-only feature in Neo4j EE and AuraDB Enterprise.

Hi David, thank you for this answer! That sounds of course like the most reasonable option.

However, I would still be interested how this can be achieved via an extension. Do have any resources on that?

Here's a reference -- check into how to build your own procedures.

A way you could do this is to define a procedure that takes a query as an argument (much as many APOC functions do, such as apoc.periodic.iterate) and to have that procedure execute the query provided -- loop through the results stream, and produce a filtered results stream omitting any column that contained a $. That way, users could run queries that resulted in this data, but the procedure would effectively act as a "post-filter".

E.g. something like this:

CALL myLibrary.specialProc("MATCH (p:Person) RETURN p.name, p.`$specialField`") YIELD result
RETURN result

the "result" object would be for example a map with {"name": "John"} and critically, missing the $specialField because it was post-filtered.

I want to stress that I do not recommend this approach. It's inferior to my earlier suggestion in every way:

  • More work for you (java coding)
  • You still have to force your query workloads to go through the procedure; they'd still be able to access $properties if they just did normal queries without the procedure

A third option would be to have a piece of middleware, like a backend. You could use a GraphQL backend or a REST API and simply have users use that to access data and not run Cypher in the first place.

Thanks for the reference. The Cypher queries are being executed by an API that acts as a middleware between the user and Neo4j. The users can pass arbitrary queries to the API and get the results, without interacting with the DB directly.

Currently, we filter the results from Neo4j for these special $ properties before we return them. However, we have to apply the filter every time even if the query result does not contain a node or edge and the filtering could be avoided in the first place.

A custom procedure that wraps around the Cypher match query would be another option. I was hoping there is a way of intercepting queries, for example something like beforeQuery and afterQuery that run on every single query and can manipulate the query result before being returned.