Reputation: 158
This may be a non-issue however I can't help but feel like there is a better way to do what I am trying to achieve.
I am writing an API in Express with my data stored in a neo4j database. I am using the official neo4j-driver to interface with neo4j which is running locally. When I run a query eg :
session
.run(`MATCH (foo:FamilyMember)-[:HAS_SISTER]->(sister:FamilyMember)
WHERE foo.firstName = 'bar'
RETURN sister.firstName AS Name, sister.lastName AS Surname
`)
.then(res => {
console.log(res);
})
Neo4j returns a response object with a lot of information about the request:
{
records: [
Record {
keys: [Array],
length: 2,
_fields: [Array],
_fieldLookup: [Object]
},
Record {
keys: [Array],
length: 2,
_fields: [Array],
_fieldLookup: [Object]
},
Record {
keys: [Array],
length: 2,
_fields: [Array],
_fieldLookup: [Object]
},
Record {
keys: [Array],
length: 2,
_fields: [Array],
_fieldLookup: [Object]
}
],
summary: ResultSummary {
query: {
text: 'MATCH (foo:FamilyMember)-[:HAS_SISTER]->(sister:FamilyMember)\n' +
" WHERE foo.firstName = 'bar'\n" +
' RETURN sister.firstName AS Name, sister.lastName AS Surname\n' +
' ',
parameters: {}
},
queryType: 'r',
counters: QueryStatistics { _stats: [Object], _systemUpdates: 0 },
updateStatistics: QueryStatistics { _stats: [Object], _systemUpdates: 0 },
plan: false,
profile: false,
notifications: [],
server: ServerInfo {
address: 'localhost:7687',
version: 'Neo4j/4.2.1',
protocolVersion: 4.2
},
resultConsumedAfter: Integer { low: 0, high: 0 },
resultAvailableAfter: Integer { low: 4, high: 0 },
database: { name: 'neo4j' }
}
}
This is a pain when really I what I want is either the actual response data as an array of objects or an error message if something fails.
I wrote this parse method to generate an array of Javascript object's with the data returned from the query:
function parseNeo4jResponseJSON(res) {
return results = res.records.reduce( (array, currentRecord) => {
const record = currentRecord.keys.reduce( (obj, key, index) => {
obj[key] = currentRecord._fields[index]
return obj
}, {})
array.push(record);
return array;
},[])
};
This works and now when I console log the query response through my parser I get it in the format I want eg:
[
{ Name: 'foo', Surname: 'bar' },
{ Name: 'foo2', Surname: 'bar2' },
...
]
Is this approach going to cause me problems down the line? Is there a better way to get a javascript object from the response? I am pretty new to neo4j. Apologies if the answer is obvious.
Upvotes: 1
Views: 597
Reputation: 8960
Based on the existing examples, what about:
session
.readTransaction((tx) =>
tx.run(`MATCH (foo:FamilyMember)-[:HAS_SISTER]->(sister:FamilyMember)
WHERE foo.firstName = 'bar'
RETURN sister.firstName AS Name, sister.lastName AS Surname`)
)
.then(results => results.records.map((record) => {
return {
Name: record.get('Name'),
Surname: record.get('Surname')
}
})
You could keep session.run
, but the session.{read,write}Transaction
variants are usually recommended because they work in every environment (where session.run
may sometimes fail in a cluster environment).
Please also make sure to use a dictionary of parameters (2nd argument of tx.run
) instead of using string interpolation, if your query needs to be parameterized. If the value of foo.firstName
comes from a variable (let's say someFirstName
), the tx.run
would become:
tx.run("MATCH (foo:FamilyMember)-[:HAS_SISTER]->(sister:FamilyMember)
WHERE foo.firstName = $firstName
RETURN sister.firstName AS Name, sister.lastName AS Surname",
{firstName: someFirstName})
Upvotes: 1