ApolloServer无法正确映射Neo4j关联节点问题求助
问题:GraphQL查询Neo4j时无法正确映射关联节点
我正在开发一个通过GraphQL查询Neo4j数据库的项目,目标是获取中心Company节点及其关联的Company或Person节点,但在JavaScript代码中无法正确映射这些关联节点。目前已成功获取中心Company节点,但connectedNodes的映射逻辑存在问题,console.log输出节点列表却未达到预期效果。我尝试过使用可选链(?.)、节点类型判断等方法,仍未解决问题,恳请提供正确的映射方案指导。
原代码片段
const { ApolloServer, gql } = require('apollo-server'); const neo4j = require('neo4j-driver'); const { GraphQLJSON } = require('graphql-scalars'); const typeDefs = gql` scalar JSON type Company { id: ID! orgNo: String! companyName: String! address: String! city: String! zipCode: String! connectedNodes: [Node] } type Person { id: ID! role: String ZipCode: String Street: String test_id: String label: String City: String RoleCode: String Name: String } type Node { id: ID! labels: [String] properties: JSON } type Query { company(orgNo: String!): Company } `; const driver = neo4j.driver( 'bolt://localhost:7687', neo4j.auth.basic('neo4j', 'password') ); const resolvers = { JSON: GraphQLJSON, Query: { company: async (_, { orgNo }) => { const session = driver.session(); const result = await session.run( `MATCH (source:Company {OrgNo: $orgNo}) OPTIONAL MATCH path = (source)-[*1..3]-(target) WHERE NONE(rel IN relationships(path) WHERE rel.RoleCode IN ['REV', 'SU']) RETURN source, COLLECT(DISTINCT target) AS connected_nodes`, { orgNo } ); await session.close(); const companyNode = result.records[0]?.get('source')?.properties; if (!companyNode) return null; const connectedNodes = result.records[0]?.get('connected_nodes')?.map(record => { const nodeType = record && record.labels?.[0]; const nodeProperties = record && record.properties; if (record && record.labels.includes('Company')) { return { id: record.identity?.toString() || null, labels: record.labels || [], properties: nodeProperties || {} }; } else if (record && record.labels.includes('Person')) { return { id: nodeProperties && nodeProperties['test_id']?.toString() || null, labels: record.labels || [], properties: nodeProperties || {} }; } return node; }) || []; // console.log(connectedNodes) const company = { id: companyNode && companyNode['identity']?.toString() || '', orgNo: companyNode && companyNode['OrgNo'] || null, companyName: companyNode && companyNode['CompanyName'] || null, address: companyNode && companyNode['Address'] || null, city: companyNode && companyNode['City'] || null, zipCode: companyNode && companyNode['ZipCode'] || '' }; return company; }, }, }; const server = new ApolloServer({ typeDefs, resolvers, }); server.listen().then(({ url }) => { console.log(`Server running at ${url}`); });
问题分析与修复方案
1. 未将关联节点加入返回对象
当前代码中已经正确生成了connectedNodes数组,但最终返回的company对象没有包含该字段,导致GraphQL接口无法返回关联节点数据。需要在company对象中添加connectedNodes属性。
2. 中心Company节点ID获取错误
companyNode是节点的properties对象,不存在identity属性。需要从原始的Neo4j节点对象(result.records[0].get('source'))中获取identity来生成ID。
3. 修复映射逻辑中的冗余与错误
- 移除未定义的
return node语句,避免返回无效值; - 简化节点属性的获取逻辑,利用可选链减少重复判断。
修复后的完整代码
const { ApolloServer, gql } = require('apollo-server'); const neo4j = require('neo4j-driver'); const { GraphQLJSON } = require('graphql-scalars'); const typeDefs = gql` scalar JSON type Company { id: ID! orgNo: String! companyName: String! address: String! city: String! zipCode: String! connectedNodes: [Node] } type Person { id: ID! role: String ZipCode: String Street: String test_id: String label: String City: String RoleCode: String Name: String } type Node { id: ID! labels: [String] properties: JSON } type Query { company(orgNo: String!): Company } `; const driver = neo4j.driver( 'bolt://localhost:7687', neo4j.auth.basic('neo4j', 'password') ); const resolvers = { JSON: GraphQLJSON, Query: { company: async (_, { orgNo }) => { const session = driver.session(); const result = await session.run( `MATCH (source:Company {OrgNo: $orgNo}) OPTIONAL MATCH path = (source)-[*1..3]-(target) WHERE NONE(rel IN relationships(path) WHERE rel.RoleCode IN ['REV', 'SU']) RETURN source, COLLECT(DISTINCT target) AS connected_nodes`, { orgNo } ); await session.close(); const sourceNode = result.records[0]?.get('source'); if (!sourceNode) return null; const companyProperties = sourceNode.properties; const connectedNodes = result.records[0]?.get('connected_nodes')?.map(node => { const nodeProperties = node.properties; let nodeId = null; if (node.labels.includes('Company')) { nodeId = node.identity?.toString(); } else if (node.labels.includes('Person')) { nodeId = nodeProperties?.test_id?.toString(); } return { id: nodeId || null, labels: node.labels || [], properties: nodeProperties || {} }; }) || []; const company = { id: sourceNode.identity.toString(), orgNo: companyProperties.OrgNo || null, companyName: companyProperties.CompanyName || null, address: companyProperties.Address || null, city: companyProperties.City || null, zipCode: companyProperties.ZipCode || '', connectedNodes // 关键:添加关联节点到返回对象 }; return company; }, }, }; const server = new ApolloServer({ typeDefs, resolvers, }); server.listen().then(({ url }) => { console.log(`Server running at ${url}`); });
内容的提问来源于stack exchange,提问作者Plot Norris
相关产品推荐
相关产品推荐

