I'm starting implementing Neo4j in my Node.js project where I first write to MongoDB within a transaction and then write to Neo4j which should fails aborts the transaction so consistency between the two is ensured. I'm getting two different errors when executing the cypher depending if I pass in a JS Object or direct parameters. If I pass the alert object and try to read its parameters I get this error:
Neo4jError: Unable to pack the given value: function() {
let states = [...arguments];
const callback = states.pop();
if (!states.length) states = this.stateNames;
const _this = this;
const paths = states.reduce(function(paths, state) {
if (_this.states[state] == null) {
return paths;
}
return paths.concat(Object.keys(_this.states[state]));
}, []);
return paths[iterMethod](function(path, i, paths) {
return callback(path, i, paths);
});
}
at captureStacktrace (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/result.js:611:17)
at new Result (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/result.js:105:23)
at newCompletedResult (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/transaction.js:501:12)
at Object.run (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/transaction.js:333:20)
at Transaction.run (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/transaction.js:174:34)
at ManagedTransaction.run (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/transaction-managed.js:56:21)
at /Users/vincenzocalia/server-node/api/src/neo4j/alert_neo4j.js:22:53
at TransactionExecutor._safeExecuteTransactionWork (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:141:26)
at TransactionExecutor.<anonymous> (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:128:46)
at step (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:52:23) {
constructor: [Function: Neo4jError] { isRetriable: [Function (anonymous)] },
code: 'ProtocolError',
retriable: false
}
so I guess that there is no mapping for the JS object. If I instead pass the object's values I get a Merge error:
Neo4jError: Invalid input 'MERGE': expected "OPTIONS" or <EOF> (line 3, column 13 (offset: 83))
" MERGE (u:User {id: $userId})"
^
at captureStacktrace (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/result.js:611:17)
at new Result (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/result.js:105:23)
at newCompletedResult (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/transaction.js:501:12)
at Object.run (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/transaction.js:333:20)
at Transaction.run (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/transaction.js:174:34)
at ManagedTransaction.run (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/transaction-managed.js:56:21)
at /Users/vincenzocalia/server-node/api/src/neo4j/alert_neo4j.js:22:53
at TransactionExecutor._safeExecuteTransactionWork (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:141:26)
at TransactionExecutor.<anonymous> (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:128:46)
at step (/Users/vincenzocalia/server-node/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:52:23) {
constructor: [Function: Neo4jError] { isRetriable: [Function (anonymous)] },
code: 'Neo.ClientError.Statement.SyntaxError',
retriable: false
}
As I understood it Merge should create a node if it doesn't exists otherwise will match a node, in my cypher I set the :Alert .id property as unique, then I get a :User node if exists or create it if it doesn't, create a :Alert node, create the :POSTED_ALERT relationship and return the alert so I can check that it was created. Can you spot what I'm doing wrong?
exports.saveAlert = async (alert) => {
console.log('neoAlert.saveAlert alert:', alert);
const driver = neo4j.getDriver();
const session = driver.session();
const userId = alert.userId;
const alertId = alert.id;
const res = await session.executeWrite(tx => tx.run(
// `
// CREATE CONSTRAINT alert_id ON (alert:Alert) ASSERT alert.id IS UNIQUE
// MERGE (u:User {id: $alert.userId})-[r:POSTED_ALERT]->(a:Alert{id: $alert.id})
`
CREATE CONSTRAINT alert_id ON (alert:Alert) ASSERT alert.id IS UNIQUE
MERGE (u:User {id: $userId})
MERGE (a:Alert {id: $alertId})
MERGE (u)-[r:POSTED_ALERT]->(a)
RETURN a AS alert
`
,
{alert ,alertId, userId}
));
await session.close();
if ( res.records.length === 0 ) {
throw new NotFoundError(`Neo4j could not create record for Alert ${alert.id} by User ${alert.userId}`);
}
console.log(`Neo4j saved ${res.records.length} alerts`);
const alerts = res.records;
const saved = alerts.length('alert');
console.log('Neo4j saved alert is: ', saved);
return saved;
// throw Error;
}