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
Related
I have a simple code that uses mongoose with nodejs to save a user object but when I log the result object that is return from save() method it is just the object I sent and the _id and id values are undefined.
Still, the object is saved correctly in the database with the new _id.
this is my code
`
import { mongoose } from "mongoose";
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {
type: String,
required: true,
},
age: {
type: Number,
required: true,
},
email: {
type: String,
required: true,
},
});
export const addUser = async (_user) => {
let user = new User({ ..._user });
let result;
try {
result = await user.save();
console.log(result._id);
} catch (err) {
console.log(err);
}
return result;
};
`
I expect console.log(result._id) to have the new generated Id but it is undefined even though it is saved correctly to the database
The solution that worked for me is to assign the _id before calling save()
export const addUser = async (_user) => {
let user = new User({ ..._user });
user._id = mongoose.Types.ObjectId();
let result;
try {
result = await user.save();
console.log(result._id);
} catch (err) {
console.log(err);
}
return result;
};
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 two collections where one holds list of systems and the other holds list of battery attached to the system. I want to use populate method so that when I run the query using system id it shows me the details of battery is also shown.
My schema for system and battery are as follows.
const mongoose = require('mongoose');
const { Schema } = mongoose;
const SystemSchema = new Schema(
{
serialNumber: String,
location: String,
BPIDs: [
{
type: Schema.Types.ObjectId,
ref: 'batteryPack'
}
]
},
{
timestamps: true
}
);
const Systems = mongoose.model('system', SystemSchema);
module.exports = Systems;
My battery model is as follows:
const mongoose = require('mongoose');
const { Schema } = mongoose;
const batteryPackSchema = new Schema(
{
systemSerialNumber: String,
batteryID: Number,
batteryVoltage: Number,
totalCurrent: Number,
stateOfCharge: Number
{
timestamps: true
}
);
const BatteryPacks = mongoose.model('batteryPack', batteryPackSchema);
module.exports = BatteryPacks;
My query route is as follows:
router.get('/details/:id', async (req, res) => {
try {
const deviceDetails = await Systems.findOne({ _id: req.params.id }).populate('batteryPack').lean();
return res.status(200).send({
deviceDetails
});
} catch (error) {
return res.status(500).send(error.stack);
}
});
On running query through postman it shows the following error:
MongooseError: Cannot populate path batteryPack because it is not in your schema. Set the strictPopulate option to
false to override.
at getModelsMapForPopulate
I was passing wrong argument inside populate method. The code is working flawlessly now.
const deviceDetails = await Systems.findOne({ _id: req.params.id }).populate('BPIDs').lean();
const deviceDetails = await Systems.findOne({ _id: req.params.id },{},{
populate: { path: 'BPIDs' },
lean: true,
})
I am new to MongoDB. I created 4 collections & they are connected with each other. (I am using node.js to write it)
Here, it's my question. How can I delete all records at once? Is there something like deep level population?
This one holds all models.
const DataModel = mongoose.Schema({
_id: { type: mongoose.Schema.Types.ObjectId, ref: 'User', require: true},
order: { type: mongoose.Schema.Types.ObjectId, ref: 'Order', require: true},
});
User model
const userSchema = mongoose.Schema({//other stuff});
Order model
const orderSchema = mongoose.Schema({
product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true },
//other stuff
});
Product model
const productSchema = mongoose.Schema({//other stuff});
I can delete the entry with these code from the database, but the other entries still there
exports.delete_data = (req, res, next) => {
const id = req.params.userId;
userDataModel.deleteOne({_id: id})
.exec()
.then(docs => {
res.status(200).json({
message: 'Record Deleted',
request: {
type: 'POST'
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
};
Update: However, I wonder, Could I call other defined delete functions for order, product inside delete_data
As #Geert-Jan suggest, cascade delete is my solution. The link that geert-jan gave solve my problem. However, I wonder, Could I call other defined delete functions for order, product inside delete_data
i did this and it could be good for someone who wants to delete documents in cascade linked to any field of a model.
async blackHole() {
try {
const rtn = new ApiResponse<any>();
const userId = id;
const accountId = mongoose.Types.ObjectId(id);
var CollectionNames: any[] = [];
mongoose.connection.db.listCollections().toArray(function (err, collections) {
CollectionNames = collections.map(c => c.name);
CollectionNames.forEach((element: any) => {
mongoose.connection.db.collection(element).deleteMany({ "account": accountId });
});
});
const accountController = new AccountController(this.wsParams);
await accountController.delete(id)
await super.delete(userId);
return rtn;
} catch (error: any) {
const rtn = new ApiResponse<any>();
rtn.message = error;
rtn.success = false;
rtn.status = 422;
return rtn;
}
}
I hope you can use it :D
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()