I am using mongoose to handle my schemas, with MongoDB, but when trying to save a new entry to a collection the save() method appears to be stuck, neither the then() method or the catch() method of the promise appear to be called.
Does anyone have any ideas?
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// const Promise = require('bluebird');
const config = require('./config');
const UserSchema = new Schema({
email: { type: String, required: true, index: { unique: true } },
name: { type: String, required: false },
password: { type: String, required: true }
});
const User = mongoose.model('User', UserSchema);
console.log('config.database.url', config.database.url);
mongoose.Promise = global.Promise;
return mongoose.createConnection(config.database.url, {
useMongoClient: true
})
.then((connection) => {
const user = new User({
email: 'someuser#somedomain.com',
password: 'xxxxx'
});
const prom = user.save();
// Displays: 'promise: Promise { <pending> }'
console.log('promise:', prom);
return prom
.then((result) => {
// Don't see this output
console.log('result:', result);
})
.catch((error) => {
// Don't see this output either
console.log('error:', error);
});
})
.catch((error) => {
console.log(error);
});
Environment: nodejs 8.9.0, node modules: Mongoose 4.13.6, mongodb 2.2.33
A little more experimenting and it would appear that I need to ensure the model is tied to the connection, such that:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// const Promise = require('bluebird');
const config = require('./config');
const UserSchema = new Schema({
email: { type: String, required: true, index: { unique: true } },
name: { type: String, required: false },
password: { type: String, required: true }
});
let User;
console.log('config.database.url', config.database.url);
mongoose.Promise = global.Promise;
return mongoose.createConnection(config.database.url, {
useMongoClient: true
})
.then((connection) => {
// associate model with connection
User = connection.model('User', UserSchema);
const user = new User({
email: 'someuser#somedomain.com',
password: 'xxxxx'
});
const prom = user.save();
// Displays: 'promise: Promise { <pending> }'
console.log('promise:', prom);
return prom
.then((result) => {
// Don't see this output
console.log('result:', result);
})
.catch((error) => {
// Don't see this output either
console.log('error:', error);
});
})
.catch((error) => {
console.log(error);
});
Alternatively we should use the connect() method that will work with the model associated via mongoose.model.
For createConnection() can be used to create multiple connections, so using a 'global' model is not supported, from what I can tell.
Saying all this it would be nice if save() didn't simply block.
Note: In researching a refinement to my answer I came across the following: Queries hang when using mongoose.createConnection() vs mongoose.connect()
Related
I am trying to update my mongodb database by Id but I am getting error userId.save is not a function. What I did was get all the databases data by Object.findById then used Object.assign to assign an updated value to the specified key then saved the updated Object back to the database. Where did I go wrong. How can I update a mongodb object by Id. Thanks in advance.
const Users = require('pathToSchema')
const userId = Users.findById('ObjectId')
Object.assign(userId, '{"email": "test#gmail.com"}')
//error arrises here. "userId.save is not a function"
userId.save()
.then((result) => {
console.log(result)
})
.catch((err) => {
console.log(err)
})
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const users_Schema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
}
}, {timestamps: true})
const Users = mongoose.model('users', users_Schema)
module.exports = Users;
The findById is not execute yet. You have to use it with a callback or an exec(). You can learn more at mogoose doc.
Try change line const userId = Users.findById('ObjectId') to const userId = await Users.findById('ObjectId').exec(). exec() will return a promise, so you could use await to get result.
Furthermore, the Object.assign statement is not correct, there is no need for the string character (which is '). It's just Object.assign(userId, {"email": "test#gmail.com"})
Try assigning the email prop instead of using Object.assign. Also bear in mind that you need to assign 2 objects but you assign a string instead.
Try this:
const userId = await Users.findById('ObjectId')
userId.email = 'test#gmail.com';
userId.save()
.then((result) => {
console.log(result)
})
.catch((err) => {
console.log(err)
})
Also, make sure you create a model from the schema and use it to findById. For instance:
const UserSchema = new Schema({
name:String,
username:{type:String, required:true, index:{unique:true}},
password:{type:String, required:true, select:false}
});
const UserModel = mongoose.model('User', UserSchema);
const user = await UserModel.findById(...);
user.save();
This worked for me.
Users.findById('ObjectId')
.then((result) => {
Object.assign(result, {
"email": "test#gmail.com"
})
result.save()
.then((result) => {
console.log(result)
})
.catch((err) => {
console.log(err)
})
})
.catch((err) => {
console.log(err)
})
I have a mongoose schema-WishlistItem, which has a validation: A new WishlistItem cannot be created if it's wishlist property(an object id) doesn't belong to a real existing Wishlist in the database. The WishlistItem has this validation so that wishlistItems without parent wishlists aren't accidentally added to the database.
How can I run tests on the WishlistItem model without creating a real wishlist?
I'm using mocha and chai.
The test to create a wishlistItem
Currently the test gives:
AssertionError: expected undefined to be an object.
This is because await WishlistItem.create({... throws an error:
ValidationError: WishlistItem validation failed: wishlist: Invalid WishlistItem "wishlist" property. No wishlist found with id: 5f9480a69c4fcdc78d55397d since we don't have that wishlist in the database.
const chai = require('chai');
const mongoose = require('mongoose');
const { expect } = chai;
const dbConnect = async (dsn) =>
mongoose.connect(dsn, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
});
const should = chai.should();
const WishlistItem = require('../testsFiles/WishlistItem.Model');
describe('Wishlist Item', () => {
before(async () => {
dbConnect(`mongodb://127.0.0.1:27017/schemaDepTest`);
});
context('create wishlist item', () => {
it('should create a wishlist item with valid arguments', async function () {
let wishlist;
try {
wishlist = await WishlistItem.create({
itemName: 'Purse',
price: '5.00',
wishlist: mongoose.Types.ObjectId('5f9480a69c4fcdc78d55397d'),
});
} catch (err) {
console.log(err);
}
expect(wishlist).to.be.an('Object');
});
});
});
WishlistItem Schema
const mongoose = require('mongoose');
const itemSchema = new mongoose.Schema(
{
itemName: { type: String, required: true, trim: true },
price: { type: String, required: true, trim: true },
wishlist: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Wishlist',
required: true,
},
},
{ timestamps: { createdAt: 'created_at' } }
);
itemSchema.path('wishlist').validate(async function (value) {
const WishlistModel = require('./Wishlist.Model');
const wishlist = await WishlistModel.findOne({ _id: value });
if (!wishlist) {
throw new Error(
`Invalid WishlistItem "wishlist" property. No wishlist found with id: ${value}`
);
} else {
return true;
}
}, 'Parent Wishlist non existent');
const WishlistItem = mongoose.model('WishlistItem', itemSchema);
module.exports = WishlistItem;
The Wishlist Schema
const mongoose = require('mongoose');
const wishlistSchema = new mongoose.Schema(
{
wishlistName: {
type: String,
required: true,
trim: true,
},
wishlistItems: [
// reference, one-to-many
{
type: mongoose.Schema.Types.ObjectId,
ref: 'WishlistItems',
},
],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
},
},
{ timestamps: { createdAt: 'created_at' } }
);
const Wishlist = mongoose.model('Wishlist', wishlistSchema);
module.exports = Wishlist;
This post answered my question
I just had to add
sinon.stub(Object.getPrototypeOf(Wishlist), 'findOne').callsFake(() => 'mock');
This way, when WishlistItem tries to validate that the Wishlist exist by calling Wishlist.findOne, () => 'mock' is called in place of findOne.
full test code:
const sinon = require('sinon');
const chai = require('chai');
const mongoose = require('mongoose');
const { expect } = chai;
const dbConnect = async (dsn) =>
mongoose.connect(dsn, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
});
const should = chai.should();
const WishlistItem = require('../testsFiles/WishlistItem.Model');
const Wishlist = require('../testsFiles/Wishlist.Model');
describe('Wishlist Item: testing dependency mocking ', () => {
before(async () => {
dbConnect(`mongodb://127.0.0.1:27017/schemaDepTest`);
});
context('create wishlist item', () => {
it('should create a wishlist item with valid arguments', async function () {
sinon.stub(Object.getPrototypeOf(Wishlist), 'findOne').callsFake(() => 'mock');
let wishlist;
try {
wishlist = await WishlistItem.create({
itemName: 'Purse',
price: '5.00',
wishlist: mongoose.Types.ObjectId('5f9480a69c4fcdc78d55397d'),
});
} catch (err) {
console.log(err);
}
console.log(wishlist);
expect(wishlist).to.be.an('Object');
});
});
});
I can not get data from my MongoDb collection via mongoose - I'm getting an empty array out of my request. It only happens when I'm using a route which I posted below.
Code
router.get("/options", async (req,res) => {
try {
const { animalClass} = req.body;
if (!animalClass) {
const animalClasses = await AnimalClass.find({});
console.log(animalClasses);
return res
.status(200)
.json({animalClasses})
} else {
const animalTypes = await AnimalType.find({class: animalClass});
console.log(animalTypes);
return res
.status(200)
.json({animalTypes})
}
} catch (err) {
res
.status(500)
.json({msg: err})
}
});
Schema
const mongoose = require('mongoose');
const animalClassSchema = new mongoose.Schema({
name: {type: String, required: true}
})
module.exports = AnimalClass = mongoose.model('animalClass',animalClassSchema);
Specify the collection name when creating the schema, like:
const animalClassSchema = new mongoose.Schema({
name: {type: String, required: true}
}, { collection: 'animalClass' });
By default, Mongoose pluralizes your collection name. This option allows you to override that behavior. More info in the docs:
https://mongoosejs.com/docs/guide.html#collection
This returns null what could be the issue? I see proper user _id in the test table, I would expect user detail to be shown in the place user. As you can see under test array i made ref to user schema.
structure as follows in database
const mongoose = require('mongoose');
let UserSchema = new mongoose.Schema({
email: String,
password: String,
});
let testSchema = new mongoose.Schema({
test: [
{
title: String,
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user',
},
},
],
});
run().catch((err) => console.log(err));
async function run() {
await mongoose.connect('mongodb://localhost:27017/test', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
await mongoose.connection.dropDatabase();
const UserModel = mongoose.model('user', UserSchema);
const TestModel = mongoose.model('test', testSchema);
const newUser = { email: 'test#test.com', password: 'Alexa123' };
const user = new UserModel(newUser);
await user.save();
const newTest = { test: [{ title: 'foo', user: user._id }] };
const test = new TestModel(newTest);
await test.save();
const getTest = await TestModel.findOne({ title: 'test' })
.populate('test.user')
.exec();
console.log(getTest, 'returns null');
}
anyway solved by this
const getTest = await TestModel.findOne({ _id: test._id })
.populate('test.user')
.exec();
I'm trying to save data in the MongoDB atlas with node.js and mongoose.
Every time I use MySchema.save(), Data is inserting But I'm also getting the error:
UnhandledPromiseRejectionWarning: MongoWriteConcernError: No write concern mode named 'majority;' found in replica set configuration
Also, there is no duplicate entry, Data is also inserting But I'm also getting the error
let User = require('../models/users.models');
const username = req.body.username;
const newUser = new User({username});
newUser.save()
.then(() => res.json('user added!'))
.catch(err => res.status(400).json('Error: ' + err));
User model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
var userSchema = new Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3
},
},
{
timestamps: true
});
const User = mongoose.model('User', userSchema);
module.exports = User;
I know it was asked 2 months ago, but for those who will encounter the same issue.
You are mistakenly entering a wrong char at the end of the URI string:
mongodb+srv://${ user }:${ password }#track-mkahl.mongodb.net/test?retryWrites=true&w=majority;
You need to delete the ; after the word majority.
This helped me.
const schema = new Schema({ name: String }, {
writeConcern: {
w: 'majority',
j: true,
wtimeout: 1000
}
});
https://mongoosejs.com/docs/guide.html#writeConcern
"mongoURI" : "mongodb+srv://${ user }:${ password }#cluster0.mde0j.mongodb.net/cluster0?retryWrites=true&w=majority "
I get the same error with this in default.json its simple error just delete the &w=majority part at the end and it will be solved
for me it was also in the URI string like #Yossi Saadi has suggested, it's just that I had majoritys written there instead of majority
I think there's something wrong with this line.
let User = require('../models/users.models');
I have created a solution for you.
/models/user.js
const mongoose = require('mongoose')
const Schema = mongoose.Schema
mongoose.connect("mongodb://localhost/stack-overflow", { useNewUrlParser: true })
var userSchema = new Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3
},
},
{
timestamps: true
});
const User = mongoose.model('User', userSchema);
module.exports = User
/routes/userroute.js
const User = require("../models/user")
// Imagine run() as an asynchronous request handler
async function run() {
try {
const user1 = new User({ username: "lidafafnus" })
user1.save((err,result) => {
console.log(err, result)
})
} catch(error) {
console.log(error)
}
}
run()