MongoDB retryWrites setup code is not working - node.js

Now, I am trying to develop the transaction session for MongoDB.
MongoDB version: 4.4.2
Mongoose version: 5.11.4
The transaction code
const session = await mongoose.startSession();
session.startTransaction();
try {
const result = await storage.create([attachment], { session: session });
await req.files.newFile.mv(attachment.filePath);
await session.commitTransaction();
return res.send(result);
} catch (err) {
console.log(err);
await session.abortTransaction();
return res.status(500).send(err);
} finally {
session.endSession();
}
When I called this code, that gave me the below error message.
MongoError: This MongoDB deployment does not support retryable writes. Please add retryWrites=false to your connection string.
So, I add retryWrites=false code in the mongoose connection code.
AS IS
const mongoose = require('mongoose');
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
poolSize: 10,
});
TO BE
const mongoose = require('mongoose');
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
retryWrites: false,
poolSize: 10,
});
But I still have the same problem...
I am not sure what is the problem.
Please MongoDB expert let me know the solution.

See Requirements for using MongoDB transactions for transaction requirements. You are probably using a standalone deployment.

Related

Mongoose connected to mongoDB but have not initialized the database

My connection code:
const mongoose = require("mongoose");
//ES6 Promise
mongoose.Promise = global.Promise;
//connect to mongoDB
mongoose.connect("mongodb://localhost/smslist", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
mongoose.connection
.once("open", function () {
console.log("Connected to database successfuly");
})
.on("error", function (error) {
console.log(`DB Connection error:`, error);
});
The mongod server terminal shows that the connection is successfull
2020-04-27T15:35:24.500+0300 I NETWORK [listener] connection accepted from 127.0.0.1:61286 #1 (1 connection now open)
2020-04-27T15:35:24.506+0300 I NETWORK [conn1] received client metadata from 127.0.0.1:61286 conn1: { driver: { name: "nodejs|Mongoose", version: "3.5.6" }, os: { type: "Windows_NT", name: "win32", architecture: "x64", version: "10.0.18362" }, platform: "'Node.js v12.16.2, LE (unified)", version: "3.5.6|5.9.10" }
The node terminal also prints
Connected to database successfuly
But when I try to use a mongoDB UI like robomongo/studio 3t/mongodb compass community, I will not see a database named smslist as expected.
I also realized that if I close the db server terminal the node terminal still shows connected to database successfully and not DB Connection error:, error as expected.
any idea?
If you haven't created any Model yet in this "smslist" database then you can not see any thing about this
You need to create some Model for this "smslist" database then you can see this in your db.
I agree it depends on the code that follows the above.
I've been working through a tutorial on this.
Here is the code and my notes on what finally worked.
// from scratch tutorial
// WORKS!!!!
//require mongoose - works
const mongoose = require('mongoose');
//define constant - works
const url = 'mongodb://127.0.0.1:27017/fruit'
// connect to datbase works as evidenced by message
mongoose.connect(url, { useNewUrlParser: true });
const db = mongoose.connection
db.once('open', _ => {
console.log('Database connected:', url)
});
db.on('error', err => {
console.error('connection error:', err)
});
//above works!! but do not see new database in mongodb
//now add schema
const Schema = mongoose.Schema
// define schema
fruitSchema = new Schema({
name: String,
rating: Number,
review: String
});
// create the model - or "collection" use singular - mongoose makes it plural
// inside database
const Fruit = mongoose.model("Fruit", fruitSchema);
//now create the document from the model (note upper and lower case)
const fruit = new Fruit({
name: "Pear",
rating: 10,
review: "good with Brie"
});
fruit.save();
//close the connection works but causes an error when trying to add a document
// mongoose.connection.close();

Warning on Connecting to MongoDB with a Node server

Connecting with MongoDB native driver
I wrote following code to connect mongodb through native driver which has been install with npm install mongodb --save
const MongoClient = require("mongodb").MongoClient;
const url = "mongodb://127.0.0.1:27017";
const dbName = "game-of-thrones";
let db;
MongoClient.connect(
url,
{ useNewUrlParser: true },
(err, client) => {
if (err) return console.log(err);
db = client.db(dbName);
console.log(`Connected MongoDB: ${url}`);
console.log(`Database: ${dbName}`);
}
);
When I write on the terminal node server.js I got following error
(node:3500) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to MongoClient.connect.
Connected MongoDB: mongodb://127.0.0.1:27017
Database: game-of-thrones
The database is connected, but how can I get rid out from the warning
Check your mongo version
mongo --version
If you are using version >= 3.1.0 change you mongo connection file to ->
MongoClient.connect("mongodb://localhost:27017/YourDB", {
useNewUrlParser: true,
useUnifiedTopology: true
})
For details about the useUnifiedTopology option added in 3.2.1, see https://github.com/mongodb/node-mongodb-native/releases/tag/v3.2.1
My advice is to leave it as it is (maybe place a warning). The useUnifiedTopology: true option does not work correctly.
More precisely, in the event of a loss of connection to the DBMS, it will never be restored. Current version 3.3.3 does not solve this problem.
Check this
I got the same error and resolved using the below template.
var MongoClient = require('mongodb').MongoClient
const client = new MongoClient(uri, {useUnifiedTopology: true});
client.connect().then((client)=>{
var db = client.db('db_name')
db.collection('collection_name').find().toArray(function (err, result) {
if (err) throw err
console.log(result);
})
})
This worked for me. and now it's not showing any DepricationWarning.
I want to add to this thread that it may also have to do with other dependencies.
For instance, nothing I updated or set for NodeJS, MongoDB or Mongoose were the issue - however - connect-mongodb-session had been updated and starting slinging the same error. The solution, in this case, was to simply rollback the version of connect-mongodb-session from version 2.3.0 to 2.2.0.
UPDATE: The issue is now fixed in connect-mongodb-session#2.3.1.
This is what made it work for me.
MongoClient.connect('mongodb://localhost:27017/blogdb', {useUnifiedTopology: true} , (err, client) =>
{
if (err) throw err;
const db = client.db('blogdb');
const collection = db.collection('posts');
const users = db.collection('users');
app.locals.collection = collection;
app.locals.users = users;
});
This is the same exact code I had before where I was getting the same deprecation message. The only difference is I haven't added the 'useUnifiedTopology: true' line.
MongoClient.connect('mongodb://localhost:27017/blogdb', (err, client) =>
{
if (err) throw err;
const db = client.db('blogdb');
const collection = db.collection('posts');
const users = db.collection('users');
app.locals.collection = collection;
app.locals.users = users;
});
yeah i got the same issue , the database was connected successfully but i used to face with warning message of deprecating warning. here are some short tips i used to handle it i hope it will help you
mongoose.connect(
database,
{useUnifiedTopology: true, useNewUrlParser: true, useCreateIndex: true })
Replace yourdbname with your variable or just link of your mongodb..
mongoose.connect(yourdbname, {useUnifiedTopology: true, useNewUrlParser: true, useCreateIndex: true })
.then(console.log("mongodb connected successfully...."))
.catch(err =>console.log(err));

Mongoose find returns no result [duplicate]

This is the code I use to connect to my database:
private connectDatabase(databaseUri: string): Promise<Mongoose.Connection> {
return Mongoose.connect(databaseUri).then(() => {
debug('Connected to MongoDB at %O', databaseUri);
return Mongoose.connection;
});
}
Today I updated Mongoose to version 4.11.0 and I got this warning when running my tests:
(node:4138) DeprecationWarning: `open()` is deprecated in mongoose >= 4.11.0,
use `openUri()` instead, or set the `useMongoClient` option if using `connect()`
or `createConnection()`
I can't find any information on how to "set useMongoClient".
Do you guys know how to?
This is how you use useMongoClient:
mongoose.connect('mongodb://localhost/advisorDemoTestDB', { useMongoClient: true })
Add { useMongoClient: true } as another argument to connect or createConnection method, its depends on version of mongoose you are using.
// Using `mongoose.connect`...
var promise = mongoose.connect('mongodb://localhost/myapp', {
useMongoClient: true,
/* other options */
});
// Or `createConnection`
var promise = mongoose.createConnection('mongodb://localhost/myapp', {
useMongoClient: true,
/* other options */
});
mongoose.connection.openUri('mongodb://127.0.0.1/camp_v12')
has anyone tried this? my deprecated warning disappeared when i use this, it was from the documentation
http://mongoosejs.com/docs/connections.html
The easiest fix for this would be to open your terminal, change your directory to your root project (folder where package.json is)
Run:
npm remove mongoose
then:
npm install mongoose#4.10.8 --save
problem solved.
Upgrading is not always the best option.
http://mongoosejs.com/docs/connections.html
Without Typescript you can pretty much ignore the issue and use Mongoose.connect(databaseUri, { useMongoClient: true }).
If you really want to avoid having the warning avoid the version 4.11.0.
I updated to version 4.11.1 and since #types/mongoose#4.7.18 are not yet updated and they do not mention the field useMongoClient in the ConnectionOptions, this is how i imported the module:
const Mongoose = require('mongoose');
And then used this function:
private connectDatabase(databaseUri: string): Promise<any> {
return Mongoose.connect(databaseUri, { useMongoClient: true })
.then(() => {
console.log('Connected to MongoDB at ', databaseUri);
return Mongoose.connection;
})
.catch(err => debug(`Database connection error: ${err.message}`));
}
As many answers say, adding { useMongoClient: true } in options argument to connect or createConnection method will solve the problem.
For e.g.
// With mongoose.connect method
mongoose.connect('mongodb://localhost/app', { useMongoClient: true });
// With createConnection method
mongoose.createConnection('mongodb://localhost/app', { useMongoClient: true });
But what is MongoClient in the first place?
From MongoDB Node.js Driver version 1.2, a new connection class MongoClient was introduced that has the same name across all the official drivers.
The new connection class MongoClient acknowledges all writes to MongoDB, in contrast to the existing DB connection class which has acknowledgements turned off.
So { useMongoClient: true } tells moongoose to use the new connection class rather than the old one
For more info click here
Connect to MongoDB with Mongoose 4.11.x (tested with both mLab single instance and MongoDB Atlas replica set):
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const options = {
promiseLibrary: global.Promise,
useMongoClient: true,
};
function connect() {
mongoose.connect(URI, options)
.then(function() {
const admin = new mongoose.mongo.Admin(mongoose.connection.db);
admin.buildInfo(function(err, info) {
if (err) {
console.err(`Error getting MongoDB info: ${err}`);
} else {
console.log(`Connection to MongoDB (version ${info.version}) opened successfully!`);
}
});
})
.catch((err) => console.error(`Error connecting to MongoDB: ${err}`));
}
module.exports = connect;
Create model:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({...});
module.exports = mongoose.model('User', userSchema);
According to the mongoose documentation, this is how useMongoClient can be set.
function connectDatabase(databaseUri){
var promise = mongoose.connect('mongodb://localhost/myapp', {
useMongoClient: true,
});
return promise;
}
The easiest fix for this:
Run this command in project root folder via terminal:
npm remove mongoose
npm install mongoose#4.10.8 --save
Problem solved.
Upgrading is not always the best option.
https://github.com/Automattic/mongoose/issues/5399
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/starbucks', {
useMongoClient: true
});
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('openUri', function() {
// we're connected!
});
Error:
(node:1652) DeprecationWarning: open() is deprecated in mongoose >= 4.11.0, use openUri() instead, or set the useMongoClient option if using connect() or createConnection().
Solution: To set useMongoClient:true in connection property
var promise = mongoose.connect('mongodb://localhost/myapp', {
useMongoClient: true,
/* other options */
});
See http://mongoosejs.com/docs/connections.html#use-mongo-client
now listening for request
It works for me using Typescript:
var dbOpt : any = {
useMongoClient: true
}
mongoose.connect(dbURI, dbOpt);
Upgrade mongoose , first you need to uninstall it with this code:
npm uninstall mongoose
Then install it again with the following code :
npm install mongoose --save

How to set useMongoClient (Mongoose 4.11.0)?

This is the code I use to connect to my database:
private connectDatabase(databaseUri: string): Promise<Mongoose.Connection> {
return Mongoose.connect(databaseUri).then(() => {
debug('Connected to MongoDB at %O', databaseUri);
return Mongoose.connection;
});
}
Today I updated Mongoose to version 4.11.0 and I got this warning when running my tests:
(node:4138) DeprecationWarning: `open()` is deprecated in mongoose >= 4.11.0,
use `openUri()` instead, or set the `useMongoClient` option if using `connect()`
or `createConnection()`
I can't find any information on how to "set useMongoClient".
Do you guys know how to?
This is how you use useMongoClient:
mongoose.connect('mongodb://localhost/advisorDemoTestDB', { useMongoClient: true })
Add { useMongoClient: true } as another argument to connect or createConnection method, its depends on version of mongoose you are using.
// Using `mongoose.connect`...
var promise = mongoose.connect('mongodb://localhost/myapp', {
useMongoClient: true,
/* other options */
});
// Or `createConnection`
var promise = mongoose.createConnection('mongodb://localhost/myapp', {
useMongoClient: true,
/* other options */
});
mongoose.connection.openUri('mongodb://127.0.0.1/camp_v12')
has anyone tried this? my deprecated warning disappeared when i use this, it was from the documentation
http://mongoosejs.com/docs/connections.html
The easiest fix for this would be to open your terminal, change your directory to your root project (folder where package.json is)
Run:
npm remove mongoose
then:
npm install mongoose#4.10.8 --save
problem solved.
Upgrading is not always the best option.
http://mongoosejs.com/docs/connections.html
Without Typescript you can pretty much ignore the issue and use Mongoose.connect(databaseUri, { useMongoClient: true }).
If you really want to avoid having the warning avoid the version 4.11.0.
I updated to version 4.11.1 and since #types/mongoose#4.7.18 are not yet updated and they do not mention the field useMongoClient in the ConnectionOptions, this is how i imported the module:
const Mongoose = require('mongoose');
And then used this function:
private connectDatabase(databaseUri: string): Promise<any> {
return Mongoose.connect(databaseUri, { useMongoClient: true })
.then(() => {
console.log('Connected to MongoDB at ', databaseUri);
return Mongoose.connection;
})
.catch(err => debug(`Database connection error: ${err.message}`));
}
As many answers say, adding { useMongoClient: true } in options argument to connect or createConnection method will solve the problem.
For e.g.
// With mongoose.connect method
mongoose.connect('mongodb://localhost/app', { useMongoClient: true });
// With createConnection method
mongoose.createConnection('mongodb://localhost/app', { useMongoClient: true });
But what is MongoClient in the first place?
From MongoDB Node.js Driver version 1.2, a new connection class MongoClient was introduced that has the same name across all the official drivers.
The new connection class MongoClient acknowledges all writes to MongoDB, in contrast to the existing DB connection class which has acknowledgements turned off.
So { useMongoClient: true } tells moongoose to use the new connection class rather than the old one
For more info click here
Connect to MongoDB with Mongoose 4.11.x (tested with both mLab single instance and MongoDB Atlas replica set):
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const options = {
promiseLibrary: global.Promise,
useMongoClient: true,
};
function connect() {
mongoose.connect(URI, options)
.then(function() {
const admin = new mongoose.mongo.Admin(mongoose.connection.db);
admin.buildInfo(function(err, info) {
if (err) {
console.err(`Error getting MongoDB info: ${err}`);
} else {
console.log(`Connection to MongoDB (version ${info.version}) opened successfully!`);
}
});
})
.catch((err) => console.error(`Error connecting to MongoDB: ${err}`));
}
module.exports = connect;
Create model:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({...});
module.exports = mongoose.model('User', userSchema);
According to the mongoose documentation, this is how useMongoClient can be set.
function connectDatabase(databaseUri){
var promise = mongoose.connect('mongodb://localhost/myapp', {
useMongoClient: true,
});
return promise;
}
The easiest fix for this:
Run this command in project root folder via terminal:
npm remove mongoose
npm install mongoose#4.10.8 --save
Problem solved.
Upgrading is not always the best option.
https://github.com/Automattic/mongoose/issues/5399
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/starbucks', {
useMongoClient: true
});
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('openUri', function() {
// we're connected!
});
Error:
(node:1652) DeprecationWarning: open() is deprecated in mongoose >= 4.11.0, use openUri() instead, or set the useMongoClient option if using connect() or createConnection().
Solution: To set useMongoClient:true in connection property
var promise = mongoose.connect('mongodb://localhost/myapp', {
useMongoClient: true,
/* other options */
});
See http://mongoosejs.com/docs/connections.html#use-mongo-client
now listening for request
It works for me using Typescript:
var dbOpt : any = {
useMongoClient: true
}
mongoose.connect(dbURI, dbOpt);
Upgrade mongoose , first you need to uninstall it with this code:
npm uninstall mongoose
Then install it again with the following code :
npm install mongoose --save

Getting list of all databases with Mongoose

There are some similar questions but all of them involves using the MongoDB NodeJS driver instead of Mongoose ODM.
I read the docs but couldn't find such functionality.
You can't directly get the list from the connection provided by mongoose, but it's easy to do with the mongo Admin object as it contains a function called listDatabases:
var mongoose = require('mongoose')
, Admin = mongoose.mongo.Admin;
/// create a connection to the DB
var connection = mongoose.createConnection(
'mongodb://user:pass#localhost:port/database');
connection.on('open', function() {
// connection established
new Admin(connection.db).listDatabases(function(err, result) {
console.log('listDatabases succeeded');
// database list stored in result.databases
var allDatabases = result.databases;
});
});
A very modern approach to get list of all mongo databases using mongoose (version 6.10.*) is to Create a mongoose connection to connect to Mongo's admin database and make sure you have an admin user.
Mongoose object is a very complex object. To list the db's :
const connection = `mongodb://${encodeURIComponent(username)}:${encodeURIComponent(password)}#${hostname}:${port}/admin`
mongoose is a very complex object with promises for executing several functions. to list the db's :
mongoose.connect(connection, { useNewUrlParser: true , useUnifiedTopology: true }).then( (MongooseNode) => {
/* I use the default nativeConnection object since my connection object uses a single hostname and port. Iterate here if you work with multiple hostnames in the connection object */
const nativeConnetion = MongooseNode.connections[0]
//now call the list databases function
new Admin(nativeConnetion.db).listDatabases(function(err, results){
console.log(results) //store results and use
});
})
Result:
{ databases:
[ { name: 'admin', sizeOnDisk: 184320, empty: false },
{ name: 'config', sizeOnDisk: 73728, empty: false },
{ name: 'local', sizeOnDisk: 73728, empty: false },
{ name: 'test', sizeOnDisk: 405504, empty: false } ],
totalSize: 737280,
ok: 1 }
If someone is looking for answers from the latest version of Mongoose and Mongodb, the below code can be used.
import mongoose from 'mongoose';
mongoose.set('strictQuery', true);
mongoose.connect('mongodb://localhost:27017/mydb', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
// Check DB Connection
db.once('open', () => {
(async () => {
const data = await mongoose.connection.db.admin().command({
listDatabases: 1,
});
console.log(data);
})();
console.log('Connected to MongoDB');
});
// Check for DB errors
db.on('error', (err) => {
console.log('DB Connection errors', err);
});
export default mongoose;
If you want to get the database list on your other functions, make sure the connection is established first and also make sure the user has admin access and then just do the below query. This is a sample from my API router.
// Get all databases
router.get('/database/get', async (req, res) => {
try {
const data = await mongoose.connection.db.admin().command({
listDatabases: 1,
});
if (data && data !== null) {
res.status(200).send({ data: data });
return;
}
res.status(200).send({ data: null, message: 'Data not found' });
} catch (e) {
// eslint-disable-next-line no-console
console.log(e);
res.status(500).send(e.message);
}
});
Try running this code. Original take from Gist.

Resources