在neo4j-graphql-js中自定义Resolver如何获取未查询的父节点字段
Great question! This is a common scenario when working with custom resolvers alongside auto-generated ones from neo4j-graphql-js. The good news is there are several ways to get the iuid value even when the client doesn't request it in their query. Let's break down the most practical solutions:
1. Use Apollo's @requires Directive (Simplest Approach)
The cleanest way is to leverage Apollo's @requires directive, which tells the GraphQL runtime that your empId resolver depends on the iuid field—even if the client doesn't include it in their query. The runtime will automatically fetch iuid and pass it to your resolver.
Update your type definition to include the directive:
type Employee { empId: String @neo4j_ignore @requires(fields: "iuid") buCode: String iuid: String name: String projectCode: String roleCode: String grade: String mailid: String duCode: String txtmailid_new: String }
With this change, your existing resolver will now have access to obj.iuid without any further code modifications. The console log will start showing the correct value instead of undefined.
2. Query the Database Directly in Your Resolver
If the @requires directive doesn't play nicely with neo4j-graphql-js's auto-generation logic, you can directly fetch the iuid using the Neo4j driver. Every node returned by neo4j-graphql-js includes an id property (the internal Neo4j node ID), which you can use to run a quick Cypher query to get the missing iuid.
Modify your resolver like this:
const resolvers = { Employee: { empId: async (obj, params, ctx, resolveInfo) => { // Grab the internal Neo4j node ID from the object const nodeId = obj.id; if (!nodeId) throw new Error("Unable to retrieve employee node ID"); // Create a session and run the Cypher query const session = ctx.driver.session(); try { const result = await session.run( `MATCH (e:Employee) WHERE ID(e) = $nodeId RETURN e.iuid AS iuid`, { nodeId } ); const iuid = result.records[0]?.get('iuid'); if (!iuid) throw new Error("iuid not found for this employee"); // Replace this with your actual REST API call // const restResponse = await fetch(`your-rest-endpoint?uid=${iuid}`); // const empId = await restResponse.json(); return `empId_for_${iuid}`; // Mock response } finally { // Always close the session to avoid leaks await session.close(); } } } };
This method is reliable and doesn't depend on any GraphQL directives—you're directly fetching the data you need from the database.
3. Modify the Query AST to Auto-Include iuid
Another option is to dynamically modify the query's Abstract Syntax Tree (AST) to add the iuid field before neo4j-graphql-js processes it. This ensures the field is fetched even if the client didn't request it.
Add a helper function to modify the AST and update your resolver:
function addIuidToQuery(info) { const selections = info.fieldNodes[0].selectionSet.selections; // Check if iuid is already in the query const hasIuid = selections.some(sel => sel.name.value === 'iuid'); if (!hasIuid) { // Add the iuid field to the selection set selections.push({ kind: 'Field', name: { kind: 'Name', value: 'iuid' } }); } } const resolvers = { Employee: { empId: async (obj, params, ctx, resolveInfo) => { addIuidToQuery(resolveInfo); // Now obj.iuid should be available console.log(obj.iuid); return `dummy_emp_id_for_${obj.iuid}`; } } };
Note that you need to ensure this AST modification happens before neo4j-graphql-js executes the query, so this works best if you hook into the resolver's execution early.
Recommendation
Start with Method 1 using the @requires directive—it's the most idiomatic GraphQL solution and requires the least code. If you run into compatibility issues with neo4j-graphql-js, Method 2 is the most robust fallback since it directly interacts with the database to get the data you need.
内容的提问来源于stack exchange,提问作者noob

