I’m currently working on a project where I retrieve data from a Neo4j database using a GraphQL query. The query returns a central Company node along with its connected nodes, which can be of type Company or Person. I’m having trouble mapping the connected nodes properly in my JavaScript code.
Here’s an excerpt of the code I’m using:
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}`);
});
I’ve been able to retrieve the central Company node successfully. However, when trying to map the connected nodes in connectedNodes, I haven’t been able to achieve the desired result. The console.log(connectedNodes) statement outputs an the nodes as list.
I suspect that there might be an issue with the mapping logic or how I’m accessing the properties of each connected node. I’ve tried various approaches, including using optional chaining (?.) and checking for the node type using conditions.
I would greatly appreciate any insights or suggestions on how to properly map the connected nodes in this scenario. Thank you!