I'm just getting started on Sequelize to write to a MSSQL db - all working well, but my node program never finishes and returns to the terminal. Code looks like this:
const Sequelize = require('sequelize');
var sequelize = new Sequelize(...);
const JournalLine = sequelize.define('journalLine', {...});
JournalLine.sync().then(() => {
JournalLine.bulkCreate([...])
});
Is there something I need to close off in order to end the program?
You did not provided callback function or utilise Promise, following will work
const Sequelize = require('sequelize');
var sequelize = new Sequelize(...);
const JournalLine = sequelize.define('journalLine', {...});
JournalLine.sync().then(() => {
return JournalLine.bulkCreate([...]).then( result => {
console.log('done');
return result;
})
});
Related
I followed this tutorial to set up MongoDB in my Next.js application: https://www.mongodb.com/developer/languages/javascript/nextjs-with-mongodb.
In a file called mongodb-config.js, I have
import { MongoClient } from 'mongodb'
const uri = process.env.MONGODB_URI
const options = {
useUnifiedTopology: true,
useNewUrlParser: true,
}
let client;
let dbPromise;
if (!process.env.MONGODB_URI) {
throw new Error('Please add your Mongo URI to .env.local')
}
// In production mode, it's best to not use a global variable.
client = new MongoClient(uri, options)
dbPromise = client.connect()
// Export a module-scoped MongoClient promise. By doing this in a
// separate module, the client can be shared across functions.
export default dbPromise
The above is how I configure my database.
When I need to use the database for my API, I do:
import dbPromise from "database/mongodb-config";
let db;
dbPromise.then((value) => {
const client = value;
db = client.db("database_name");
})
.catch((error)=>{
console.error(error);
});
db will be the variable that links to my database.
Now, I want to simplify this process and put everything in one file.
In the portion where I set up dbPromise in mongodb-config.js, I initialize the DB variable and export it:
client = new MongoClient(uri, options)
dbPromise = client.connect()
let db;
dbPromise.then((value)=>{
const client = value;
db = client.db("datatbase_name");
})
.catch((error)=>{
console.error(error);
});
export default db
I totally expect this to work. However, when I import db to another file and use it, the db is null. However, I waited until the dbPromise is resolved to pass db a value.
Use await like this.
dbPromise = client.connect()
let db;
await dbPromise.then((value)=>{
const client = value;
db = client.db("datatbase_name");
})
.catch(error){
console.error(error);
}
export default db
because mongoose is asynchronous so we have to use await before dbPromise otherwise export will be executed first before dbPromise.
Try this, instead of returning db, return an async function, which you can all with await, in other parts to obtain, the connection to the database, the function will not try to make repeated connections, if they are already present:
let db, connection;
async function dbSetup() {
try {
if(!connection) {
connection = await client.connect();
}
if(!db) {
db = await connection.db("datatbase_name");
}
return db;
} catch(error){
console.error(error);
}
}
export default dbSetup;
Another way is if you have node version 14.8 or greater, you can use top-level await functionality, which is basically using await, not inside an async function, like this:
client = new MongoClient(uri, options);
dbPromise = await client.connect();
let db = await dbPromise.db("datatbase_name");
export default db;
I know we have various packages avalable on GitHub to query MongoDB using NodeJS. They don't solve my use case. I am looking to execute MongoDB Shell commands from NodeJS which are different from MongoDB NodeJS commands
Example: NodeJS
db.collection('user').find({})
Example: MongoDB Shell
db.getCollection('user').find({})
Notice 'collection' and 'getCollection' are different.
I want to save MongoDB Shell queries as text. How do I execute those queries once I have read them from the database?
Try this adapted from the MongoDB documentation:
const { MongoClient } = require("mongodb");
// Replace the uri string with your MongoDB deployment's connection string.
const uri =
"mongodb+srv://<user>:<password>#<cluster-url>?w=majority";
const client = new MongoClient(uri);
async function run() {
try {
await client.connect();
const db = client.db("myDatabase");
const result = await db.getCollection('user').find({});
console.log(result);
} finally {
await client.close();
}
}
run().catch(console.dir);
You can use child_process library of NodeJs but it is litte bit tricky. You must wait for mongo shell to finish its words.
const { spawn } = require("child_process");
const child = spawn("/usr/bin/mongo");
setTimeout(() => {
child.stdin.write("show dbs\n");
}, 5000);
child.stdout.on("data", (data) => {
console.log(`command line says:\n${data}`);
});
Lets Try this code -
let { MongoClient } = require('mongodb');
const url =
`mongodb+srv://${process.env.DB_USER}:${process.env.DB_USER_PASSWORD}#
${process.env.DB_CLUSTER}.mongodb.net`;
async function connectDatabase() {
const client = await MongoClient.connect(url, {
useNewUrlParser: true,
useUnifiedTopology: true
});
const db = client.db("main");
return {
listings: db.collection("test_listings")
};
};
module.exports = { connectDatabase };
I am struggling with promises, async/await. Here i want to export the gridfs object to another file but when I import it using require and execute console.log(gridfs) it gives an empty object. Can anyone help how i could export gridfs
const mongoose = require('mongoose');
async ()=> {
await mongoose.connection.on('connected', ()=>{
const gridfs = require('mongoose-gridfs')({
collection: 'sharedfiles',
model: 'SharedFiles',
mongooseconnection: mongoose.connection
});
global.sharedfile = gridfs;
});
module.exports = sharedfile;
}
file where i need gridfs:
const sharedfile = require('path to above file');
//under another promise
rslt.data.on('end', ()=>{
console.log(sharedfile);
}
the result i am getting is {} because console.log runs before the script loads can anyone suggest how to fix it. (I am new with promises and async/await).
Two things.
First, you never actually call your anonymous async function.
Second, your export is in the scope of that function so it never gets set. Therefore your require returns the empty contents '{}' of module.export.
Try something like this.
const mongoose = require('mongoose');
module.exports = async ()=> {
await mongoose.connection.on('connected', ()=>{
const gridfs = require('mongoose-gridfs')({
collection: 'sharedfiles',
model: 'SharedFiles',
mongooseconnection: mongoose.connection
});
global.sharedfile = gridfs;
return gridfs;
});
}
Then, your export provide the async function (a Promise) to the requiring code. You invoke it with () and use .next to handle its returned result.
require('path to above file') ()
.next(
function (gridfs) {
console.log (gridfs)
} )
.catch (...)
Or you can require it and then invoke it later.
const getGridFs = require('path to above file')
...
getGridFs ( )
.next (gridfs => {console.log(gridfs)})
.catch (error => {console.error(error)})
Be patient: you'll figure it out.
Below code throw "TypeError: sequelize.transaction is not a function" Error
sequelize.transaction(transaction => {
myDb.myTable.findAll({attributes:['IMAGEPATH'],where:{ID : customerId}})
.then((result) => {
....
}).then((commitResult) =>{
//commit
}).catch((rollbackErr) =>{
//rollback
})
It looks like you're trying to reference the transaction function on the definition as opposed to the instance i.e.
const sequelize = require('sequelize');
sequelize.transaction(...); // doesn't exist
You need to create a sequelize instance and use the transaction function on this
const Sequelize = require('sequelize');
const db = new Sequelize(...);
db.transaction(...); // works
See the docs.
Suppose I have a the following module, as database.js
const initOptions = {}
const pgp = require('pg-promise')(initOptions)
const config = require('../../config')
const db = pgp({
host: config.database.host,
port: config.database.port,
database: config.database.database,
user: config.database.user,
password: config.database.password
})
module.exports = db
And the following module as create.js
const db = require('./database')
function create (name) {
return new Promise((resolve, reject) => {
db.func('create', name)
.then(data => {
return resolve(data)
})
.catch(err => {
return reject(err)
})
})
}
module.exports = create
I'm trying to run a unit test on create.js that will test that db.func is called with 'create' as first argument and 'name' as the second, but without actually needing to set up a database connection (So tests can run offline).
From what I can gather, this is what libraries like sinon.JS can be used for, so I tried creating a test and stubbed the db object.
const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')
chai.use(chaiAsPromised)
const sinon = require('sinon')
const expect = chai.expect
const create = require('./create.js')
describe('Test Module', () => {
it('should test stuff', () => {
const db = require('./database')
const dbStub = sinon.stub(db, 'func').callsFake(Promise.resolve(null))
expect(create('test').then).to.be.a('Function')
})
})
However, it fails with
TypeError: Cannot redefine property: func
Most likely due to my limited exposure to sinon...
How do I go about stubbing (or maybe I need to mock?) the db function so that I can test it an ensure db.func was called?
You can make the properties configurable by disabling locks with the no noLocking option in Initialization Options. This allows sinon to replace the properties:
const initOptions = { noLocking : true };
On a related note:
Your create function is creating an unnecessary promise wrapper, which is a promise anti-pattern. You should just return the result from db.func, which is a promise already:
function create(name) {
return db.func('create', name);
}
Also callsFake takes a function and you are giving it a promise. Use returns instead:
const dbStub = sinon.stub(db, 'func').returns(Promise.resolve(null))
I'm having trouble setting the noLocking option. The docs state it can be set after initialization, however if I set it with db.$config.options.noLocking = true, the same error occurs. However, if I set it in the database.js init options it works fine.
From the author of pg-promise...
It is because at that point the noLocking can only affect tasks and transactions. And since the db level of the protocol is initiated only once, setting noLocking after the library's initialization doesn't effect it.
I have just updated the documentation to clarify it:
This option is dynamic (can be set before or after initialization). However, changing it after the library's initialization will not affect Database objects that have already been created.