I am trying to add a node to a neo4j database in a node.js app and the code seems to execute fine, but no node is created.
Here is my code:
var neo4j = require('neo4j-driver');
// the rest of my program
const driver = new neo4j.driver(
"bolt://localhost:7687",
neo4j.auth.basic(neouser, neopass)
);
const session = driver.session();
var cypher =
"MERGE (b:TRIGGER {name:'" +
rname +
"'}) MERGE (c:FIELD{name:'" +
trigger +
"'}) MERGE (b)<-[:ACTIVATES]-(c)";
try {
const result = session.run(cypher);
console.log(result);
} finally {
console.log("finally");
session.close();
}
driver.close();
and the Error result:
Result {
_stack: '\n' +
' at captureStacktrace (C:\\NGToolbox\\NGToolBox\\node_modules\\neo4j-driver\\lib\\result.js:263:15)\n' +
' at new Result (C:\\NGToolbox\\NGToolBox\\node_modules\\neo4j-driver\\lib\\result.js:68:19)\n' +
' at Session._run (C:\\NGToolbox\\NGToolBox\\node_modules\\neo4j-driver\\lib\\session.js:174:14)\n' +
' at Session.run (C:\\NGToolbox\\NGToolBox\\node_modules\\neo4j-driver\\lib\\session.js:135:19)\n' +
' at C:\\NGToolbox\\NGToolBox\\routes\\bizrulevis.js:261:30\n' +
' at Layer.handle [as handle_request] (C:\\NGToolbox\\NGToolBox\\node_modules\\express\\lib\\router\\layer.js:95:5)\n' +
' at next (C:\\NGToolbox\\NGToolBox\\node_modules\\express\\lib\\router\\route.js:137:13)\n' +
' at Route.dispatch (C:\\NGToolbox\\NGToolBox\\node_modules\\express\\lib\\router\\route.js:112:3)\n' +
' at Layer.handle [as handle_request] (C:\\NGToolbox\\NGToolBox\\node_modules\\express\\lib\\router\\layer.js:95:5)\n' +
' at C:\\NGToolbox\\NGToolBox\\node_modules\\express\\lib\\router\\index.js:281:22',
_streamObserverPromise: Promise { <pending> },
_p: null,
_query: "MERGE (b:TRIGGER {name:'DELETEME.1'}) MERGE (c:FIELD{name:'4001'}) MERGE (b)<-[:ACTIVATES]-(c)",
_parameters: {},
_connectionHolder: ConnectionHolder {
_mode: 'WRITE',
_database: '',
_bookmark: Bookmark { _values: [] },
_connectionProvider: DirectConnectionProvider {
_id: 3,
_config: [Object],
_log: [NoOpLogger],
_userAgent: 'neo4j-javascript/0.0.0-dev',
_authToken: [Object],
_connectionPool: [Pool],
_openConnections: [Object],
_address: [ServerAddress]
},
_referenceCount: 1,
_connectionPromise: Promise { <pending> }
}
}
finally
When I go into Neo4j the db is still empty.
I have confirmed that it is active, that I can use that same cypher to create a node, that the connection is being established in the security log and it is not failing due to un/pw. Everything looks perfect, except for the whole nothing created issue.
Thank you for any advice.
edit: added the driver call and the driver close from outside the snippets scope.
This code should work for you (assuming neouser, neopass, rname, and trigger are defined):
const neo4j = require('neo4j-driver');
async function doIt() {
const driver = neo4j.driver(
"bolt://localhost",
neo4j.auth.basic(neouser, neopass)
);
const session = driver.session();
try {
await session.writeTransaction(async txc => {
var result = await txc.run(
`MERGE (b:TRIGGER {name: $rname})
MERGE (c:FIELD {name: $trigger})
MERGE (b)<-[:ACTIVATES]-(c)
RETURN b, c`,
{rname: rname, trigger: trigger}
)
result.records.map(record => {
console.log(`b: ${record.get('b')}, c: ${record.get('c')}`);
})
})
} finally {
console.log("finally");
await session.close();
await driver.close();
}
}
doIt();
This code is aware of the asynchronous nature of the processing, uses the result after the transaction has completed, and only then closes the session and driver. It also uses a writeTransaction to write to the DB.
You should study the driver's github documentation to get an idea of all the ways the driver can be used.
If you are writing some API, try to use an OGM
https://www.npmjs.com/package/neo4j-node-ogm
class SomeModel extends from Model {} //see documentation
and to persist
const a = new SomeModel()
await a.save()
Tell me if that helps you.
Related
I'm trying the following code:
const Conn = mongoose.createConnection('mongodb://127.0.0.1:27017/db');
const addresses = Conn.collection('users').aggregate([
{
$project: {
_id: false,
ethAddr: true,
}
}
]);
I receive the following error:
[...]\backend\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:100
throw new Error('Collection method ' + i + ' is synchronous');
^
Error: Collection method aggregate is synchronous
at NativeCollection.<computed> [as aggregate] ([...]\backend\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:100:15)
at file:///[...]/backend/scripts/dbGetMerkleRoot.js:11:46
at file:///[...]/backend/scripts/dbGetMerkleRoot.js:28:3
at ModuleJob.run (node:internal/modules/esm/module_job:185:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:281:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:65:12)
What in cattle's name I'm doing wrong?
It seems to be a problem with the way mongoose connects to the database. Creating the connection but not connecting prior to invoking the aggregation method causes that exception to be thrown. I should've used it this way:
// create custom connection
const Conn = mongoose.createConnection();
// connect to database
await Conn.openUri('mongodb://127.0.0.1:27017/db');
// #type {AggregationCursor}
const addresses = Conn.collection('users').aggregate([
{
$project: {
_id: false,
ethAddr: true,
}
}
]);
console.log( await addresses.toArray() );
It's frustrating the exception itself is poorly documented.
I want to send notification to multiple devices and for that am getting the token via querying the docs and saving the token to array but it shows that array is empty. Most probably error is because am not able to add elements in the array.
My code is:-
var registrationTokens=[];
const indexOfSender=usersList.indexOf(chatItem.senderUsername);
let removedUsername=usersList.splice(indexOfSender,1); //to remove the senders name from list
usersList.forEach(async(element)=>{
const query = admin.firestore().collection('users').where("username","==",element);
const querySnapshot = await query.get();
if (querySnapshot.docs.length > 0) {
const doc = querySnapshot.docs[0];
const data = doc.data();
registrationTokens.push(data.androidNotificationToken); //adding token over here
}
else {
console.log("Unable to get token for the username ", element);
}
});
const message =
{
notification: {
title:'Message',
body: body,
imageUrl: url,
},
tokens: registrationTokens,
data: { recipient: senderUserId },
};
admin.messaging().sendMulticast(message)
.then(response =>
{
if (response.failureCount > 0) {
const failedTokens = [];
response.responses.forEach((resp, idx) => {
if (!resp.success) {
failedTokens.push(registrationTokens[idx]);
}
});
console.log('List of tokens that caused failures: ' + failedTokens);
}
else
{
console.log('Successfully sent messages ', response);
}
});
Error
Error: tokens must be a non-empty array
at FirebaseMessagingError.FirebaseError [as constructor] (/workspace/node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseMessagingError.PrefixedFirebaseError [as constructor] (/workspace/node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseMessagingError (/workspace/node_modules/firebase-admin/lib/utils/error.js:254:16)
at Messaging.sendMulticast (/workspace/node_modules/firebase-admin/lib/messaging/messaging.js:294:19)
at sendNotificationForGroupChat (/workspace/index.js:238:35)
at exports.onCreateMessage.functions.region.firestore.document.onCreate (/workspace/index.js:116:9)
at process._tickCallback (internal/process/next_tick.js:68:7)
async inside forEach does not work the way you expect. If you add some logging, you will see that the loop ends before any of its async work is complete, leaving your tokens array empty before you pass it to FCM. Each iteration through the loop simply generates a promise that is not resolved. You will need to rewrite the code to actually wait for all those promises before calling FCM.
Read more about that:
Using async/await with a forEach loop
for-of loop will work just fine with asynchronous calls :)
Cheers
I have a funciton called getSpidFromOvr()
const mysql = require('mysql2/promise');
async function gopher(param1, param2){
let param3 = parseInt(param1 - ovrUpgrade[param2 - 1]);
const db = await mysql.createConnection({
host: 'localhost',
user: 'root',
database: 'default_schema'
});
db.connect();
let res = await db.query({
sql: "SELECT `id` FROM `players` WHERE `param` = ? LIMIT 1",
values: [param3]
});
db.end();
return await res;
}
which I call in my main() function,
function main(){
// First, get the ovr
gopher(101, 5)
.then((res) => {
let row = res[0]; // [ TextRow { id: 100 } ]
console.log(row.id); // Returns undefined
})
}
Why is it that row returns a valid object (using typeof row returns object) but when I try to access the element id of row, it returns undefined?
Figured it out. Instead of doing
res[0].id
I did
res[0][0].id
Certainly a bit weird since I was able to call res[0].id if I were to use the callback function, but hope this helps anyone who comes across this issue.
I am very new to the graph database ecosystem and for start I am experimenting with the neo4j. I would very much like to work with node and neo4j. So after a quick search I found neo4j-driver that is an officially supported driver for JavaScript and an example provided which is:
const neo4j = require('neo4j-driver')
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
const session = driver.session()
const personName = 'Alice'
try {
const result = await session.run(
'CREATE (a:Person {name: $name}) RETURN a',
{ name: personName }
)
const singleRecord = result.records[0]
const node = singleRecord.get(0)
console.log(node.properties.name)
} finally {
await session.close()
}
// on application exit:
await driver.close()
now when I run this code, I immediately get the following error:
SyntaxError: await is only valid in async function
Now I thought I understood the error that I would have to wrap the try-catch block with anonymous async function to get rid of the error. The changed code body is:
const config = {
"neo4j": {
"url": "neo4j://localhost",
"authUser": "neo4j",
"authKey": "adminPassword"
}
}
const neo4j = require("neo4j-driver");
const driver = neo4j.driver(
config.neo4j.url,
neo4j.auth.basic(config.neo4j.authUser, config.neo4j.authKey)
);
const session = driver.session();
(async () => {
try {
const result = await session.run('CREATE (a:Person {name: $name}) RETURN a', { name: 'Alice' });
const singleRecord = result.records[0];
const node = singleRecord.get(0);
console.log(node.properties.name);
} catch (error) {
console.log("Error Body: ", error);
} finally {
await session.close();
}
})();
await driver.close();
But to my dismay, I have run into another error that is very cryptic:
{ Neo4jError: Could not perform discovery. No routing servers available. Known routing table: RoutingTable[database=Sample database, expirationTime=0, currentTime=1592397056399, routers=[], readers=[], writers=[]]
at captureStacktrace (/Users/pc/node_modules/neo4j-driver/lib/result.js:263:15)
at new Result (/Users/pc/node_modules/neo4j-driver/lib/result.js:68:19)
at Session._run (/Users/pc/node_modules/neo4j-driver/lib/session.js:174:14)
at Session.run (/Users/pc/node_modules/neo4j-driver/lib/session.js:135:19)
at /Users/pc/neoNode.js:20:38
at Object.<anonymous> (/Users/pc/neoNode.js:31:3)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12) code: 'ServiceUnavailable', name: 'Neo4jError' }
I also had some problems with this.
First off, Natam Oliveira is correct. You need to use the bolt protocol, and await promises needs to be within an async function. For some reason the neo4j protocol is used in some examples in the docs. Additionally it would seem both examples currently provided by Neo4j—in the driver-manual and javascript-driver section—causes errors if you use them outside of some kind of unspecified environment.
There were some clues on the npmjs pagckage page, though, so by working them into the existing code, I was at least able to spit out some data. However I'm also wondering on how you could make this work inside the async function, so an explanation to how that could work with this driver would be very welcome.
Here's what worked for me:
const neo4j = require('neo4j-driver')
const cnx = {
user: 'neo4j',
password: 'some passphrase',
uri: 'bolt://localhost:7687'
}
const driver = neo4j.driver(cnx.uri, neo4j.auth.basic(cnx.user, cnx.password))
driver.verifyConnectivity()
.then((cnxMsg) => {
console.log(cnxMsg)
})
const session = driver.session({ database: 'neo4j' })
session.run('MATCH (n:Movie) RETURN n LIMIT 5')
.subscribe({
onKeys: keys => {
console.log(keys)
},
onNext: record => {
console.log(record.get('n').properties.title)
},
onCompleted: () => {
session.close()
},
onError: error => {
console.error(error)
}
})
This spits out some movies using the streaming API as seen in the NPM documentation. (Note: It will only work if you started/installed the Movie database, so double check that you didn't delete it, as its deletion is also part of the Neo4j tutorial.) Now just change the MATCH Cypher query to whatever you like, and play around with the output, for instance by piping it to Express.
Sources:
https://neo4j.com/docs/driver-manual/current/client-applications/
https://neo4j.com/developer/javascript/#javascript-driver
https://www.npmjs.com/package/neo4j-driver
https://neo4j.com/docs/api/javascript-driver/current/
first of all, I think your URL should be "url": "bolt://localhost:7687"
And you still with await driver.close() outside an async function
If you are starting to use neo4j, look for an OGM (Object Graph Model) to help you.
The second error is relatively straighforward to understand.
The first is a bit more challenging.
I have tried different combination to overcome this error but none improvement occurs.
My console returns me:
// console log > first promise { ReplyError: ERR new objects must be
created at the root
at parseError (node_modules/redis-parser/lib/parser.js:193:12)
at parseType (node_modules/redis-parser/lib/parser.js:303:14) command: 'JSON.SET', args: [ 'jsonTest7',
'.user.here.now',
'{".nestedValue": "I am a nested value"}' ], code: 'ERR' } // console log > second promise // console log > jsonTest7 response:
null
Here my snippet.js:
const redis=require("redis");
rejson = require('redis-rejson');
const {promisify} = require('util');
rejson(redis); /* important - this must come BEFORE creating the client */
let client= redis.createClient({
port:6380,
host:'localhost',
});
const setAsync = promisify(client.json_set).bind(client);
const getAsync = promisify(client.json_get).bind(client);
const existsAsync= promisify(client.exists).bind(client);
client.exists('jsonTest2', function(err, reply) {
if (reply === 1) {
return true
} else {
return false
}
});
async function isExist(object){
var isExist= await existsAsync(object).then(data=> data)
.catch((err) => console.error(err));
console.log("isExist: ", typeof isExist)
if(isExist !== 1) {
console.log("creating object...")
await setAsync(object, '.', '{"here":"something"}');
console.log("object created: " + object)
}
}
async function myFunc(object, rootKey) {
console.log("then 1")
await isExist(object)
await setAsync(object, ".user.here.now", '{".nestedValue": "I am a nested value"}')
.catch((err) => console.error(err));
console.log("then 2")
const res = await getAsync(object, '.user.here.now')
.catch((err) => console.error(err));
console.log(object + " response: ", res)
}
myFunc("jsonTest7")
Any hint would be great,
thanks
The first error means that you're trying to create a new document - i.e. the RedisJSON key does not exist - but are only supplying a subdocument (i.e. '.user.here.now'). New keys must be set to the root ('.') level like your current code sample shows.