Skip to main content
Here is a comprehensive example implementation covering:
  1. Setting up the Access Control graph structure.
  2. A single, efficient query to populate Neo4j with document data, vectors, and graph context.
  3. How to perform a secure, role-based vector search that respects the access rules.

Part 1: Initial Setup - Modeling Access Control in Neo4j

This is a one-time setup (or something you’d manage via an admin panel). We will create the graph structure that represents your RBAC rules. The core idea is to model Roles, Document Classes, and the Hierarchy of Confidentiality as nodes in the graph.

Step 1.1: Create Confidentiality Level Hierarchy

This is the most powerful part. We model the “includes” relationship between levels.
Now, if a role has access to ‘Confidential’, we can easily query if it also has access to ‘Private’ by traversing the [:INCLUDES] path.

Step 1.2: Create Document Classes and Roles

Step 1.3: Assign Permissions to Roles

Now we connect the roles to the rules.
With this graph structure in place, the foundation for secure querying is set.

Part 2: Populating Neo4j from Laravel

In your ProcessDocumentJob, after getting the results from docling and Gemini, you will execute a single, powerful Cypher query. Assumptions:
  • You have created a vector index:
  • Your Laravel job has the following data prepared:

The All-in-One Cypher Query

This query will be executed with the data above as parameters.
You would execute this from your Laravel job using a Neo4j client library, passing all your data in one go. This is highly efficient.

Part 3: Secure, Role-Based Querying from Laravel

This is where everything comes together. When a user performs a search in your Laravel app, your backend will:
  1. Get the user’s role (e.g., ‘Researcher’).
  2. Convert the user’s search query into a vector using the Gemini API.
  3. Execute the following secure Cypher query, passing the role and query vector as parameters.

The Secure Hybrid Query (Vector Search + Access Control)

How it Works:

  • A FinanceAnalyst searching for “company performance” will get results from FinancialReport documents. They will not see any ResearchPaper documents, even if they are a perfect vector match.
  • A Researcher searching for the same term will get results from ResearchPaper documents but not from FinancialReport documents.
  • If a TopSecret document exists, neither the Researcher nor the Analyst will see it in their results, regardless of the query. Only an Admin would.
  • The [:INCLUDES*0..] syntax is a variable-length path match. It means “find a path of zero or more INCLUDES relationships,” which is a very efficient and declarative way to check hierarchical permissions.
By designing your graph this way, you bake your business’s access control rules directly into the database structure, leading to queries that are both powerful and secure by default.