Mongoose query not returning values - node.js

I have a CosmosDB collection called plotCasts, which has objects that look like this:
{
...
"owner" : "winery",
"grower" : "Bill Jones",
...
}
I have the following Mongoose schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const plotCastSchema = new Schema({
owner: String,
grower: String,
...
});
const ModelClass = mongoose.model('plotCast', plotCastSchema);
module.exports = ModelClass;
However, when I query the database using the query below, I get an empty array for a result. Any idea why?
PlotCast.find({ owner: 'winery' }).lean().exec(function(err, results) {
if (err) {
res.send(err);
} else if (!results) {
res.send(null);
} else {
res.send(results);
}
});

Okay, you named your model plotCast but your collection is plotCasts.
You can force your collection name this way:
const plotCastSchema = new Schema({
owner: String,
grower: String,
...
}, { collection: 'plotCasts' });
Or, simply define your Model in mongoose with the collection name as first argument, this way:
const ModelClass = mongoose.model('plotCasts', plotCastSchema);
Please let me know if that's it :)

the problem is naming the db always saves schema in plural form so it should be like below
PlotCasts.find({ owner: 'winery' }).lean().exec(function(err, results) {
if (err) {
res.send(err);
} else if (!results) {
res.send(null);
} else {
res.send(results);
}
});

Related

mongoose.Schema.Types.ObjectId is giving an empty array when console.logged

This is my table schema
var mongoose=require("mongoose");
var tableSchema=new mongoose.Schema({
tName:String,
keys:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"key"
}
],
fields:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"field"
}
]
})
module.exports=mongoose.model("table",tableSchema);
----Key Schema
var mongoose=require("mongoose")
var keySchema=new mongoose.Schema({
name:[String],
value:[String]
})
module.exports=mongoose.model("key",keySchema);
---field Schema
var mongoose=require("mongoose")
var fieldSchema=new mongoose.Schema({
name:[String],
value:[String]
})
module.exports=mongoose.model("field",fieldSchema);
----How I Pushed into
app.post("/table/:id/value",function(req,res){
var Key={
name:req.body.key,
value:req.body.keyValue
}
var Field={
name:req.body.field,
value:req.body.fieldValue
}
table.findById(req.params.id,function(err,foundTable){
if(err){
console.log(err)
}
else{
console.log(foundTable)
key.create(Key,function(err,createKey){
foundTable.keys.push(createKey)
console.log(createKey)
})
field.create(Field,function(err,createField){
foundTable.fields.push(createField)
console.log(createField)
})
foundTable.save();
console.log(foundTable);
res.redirect("/table/"+req.params.id)
}
})
})
ObjectId are not being refernced
Here is the Image that prints the table
How I populated the table
app.get("/table/:id",function(req,res){
table.findById(req.params.id).populate("keys").populate("fields").exec(function(err,foundTable){
if(err){
console.log(err)
res.redirect("/")
}
else{
console.log(foundTable);
res.render("show",{table:foundTable})
}
})
})
I Dont know where I had gone wrong,
everything seems to be fine but
the objected is not referenced when printed and
it is not being populated
How it should be printed reference: https://bezkoder.com/mongoose-one-to-one-relationship-example/
This is an example:
1st schema
const mongoose = require("mongoose");
const Customer = mongoose.model(
"Customer",
new mongoose.Schema({
name: String,
age: Number,
gender: String
})
);
module.exports = Customer;
2nd schema
const mongoose = require("mongoose");
const Identifier = mongoose.model(
"Identifier",
new mongoose.Schema({
cardCode: String,
customer: {
type: mongoose.Schema.Types.ObjectId,
ref: "Customer"
}
})
);
module.exports = Identifier;
How it should be printed
{
_id : ObjectId("5da000be062dc522eccaedeb"),
cardCode : "5DA000BC06",
customer : ObjectId("5da000bc062dc522eccaedea"),
__v : 0
}
How it should be populated
[ { _id: 5da135bf61a1dd3e9c2a6e82,
cardCode: '5DA135BD61',
customer:
{ _id: 5da135bd61a1dd3e9c2a6e81,
name: 'bezkoder',
age: 29,
gender: 'male',
__v: 0 },
__v: 0 } ]
try this .populate([ 'keys', 'fields' ])
The reason why keys and fields are not inserted is that the foundTable.save() will be executed before creating the new Key and Field documents and push there _id to the foundTable.
One way to solve the issue is by using async/await. You can modify your code as below using async/await
app.post("/table/:id/value", async function (req, res) {
var Key = {
name: req.body.key,
value: req.body.keyValue,
};
var Field = {
name: req.body.field,
value: req.body.fieldValue,
};
try {
const foundTable = table.findById(req.params.id);
const createKey = await key.create(Key);
const createField = await field.create(Field);
foundTable.keys.push(createKey._id);
foundTable.fields.push(createField._id);
await await foundTable.save();
res.redirect("/table/"+req.params.id)
} catch (err) {
console.log(err);
// handle failure here
}
});
This will make sure the Key and Field are created and _id is pushed to foundTable before saving the foundTable
Regarding the populate query. Looks like once you save the _id of Field and Key in foundTable your existing query itself should work

updating nested documents in mongoDB(node.js)

i am trying to update a value in the object of my embedded schema(comments schema) whose value i had previously stored 0 by default. i have tried all the ways to update but none of the stackoverflow answer worked.
my code is
var checkedBox = req.body.checkbox;
User.updateOne({_id: foundUser._id},{$set :{comments:{_id :checkedBox,cpermission:1,}}},function(err,updatec){
if(err){
console.log(err);
}
else{
console.log("successfull");
console.log(updatec);
}
});
i had comment schema nested in user schema,here foundUser._id is the particular users id,and checkedBox id is the embedded objects particular id. previously my cpermission was 0,set by default,but now i want to update it to 1. although this is updating my schema,but deleting the previous images and comments in the schema aswell.
where am i going wrong?
here is my schema
const commentSchema = new mongoose.Schema({
comment: String,
imagename: String,
cpermission:{type:Number,default:0},
});
const Comment = new mongoose.model("Comment", commentSchema);
const userSchema = new mongoose.Schema({
firstname: String,
lastname: String,
email: String,
password: String,
comments: [commentSchema],
upermission:{type:Number,default:0},
});
userSchema.plugin(passportLocalMongoose);
const User = new mongoose.model("User", userSchema);
First, you need to convert checkbox in the array, as it will be a string if you select a single element
Then wrap it with mongoose.Types.ObjectId as a precaution
Then you can use arrayFilters to update multiple matching array elements
var checkedBox = req.body.checkbox;
if (!Array.isArray(checkedBox)) {
checkedBox = [checkedBox]
}
checkedBox = checkedBox.map(id => mongoose.Types.ObjectId(id))
User.updateOne(
{ _id: foundUser._id }, // filter part
{ $set: { 'comments.$[comment].cpermission': 1 } }, // update part
{ arrayFilters: [{ 'comment._id': {$in: checkedBox }}] }, // options part
function (err, updatec) {
if (err) {
console.log(err);
}
else {
console.log("successfull");
console.log(updatec);
}
});
your comment is the array of documents. if you want to update an element of an array must be select it. for that must be added another condition to the first section of updateOne then in seconde section use $ for update selected element of the array.
User.updateOne(
{_id: foundUser._id, 'comments._id': checkedBox},
{
$set: {'comments.$.cpermission': 1}
}
, function (err, updatec) {
if (err) {
console.log(err)
}
else {
console.log('successfull')
console.log(updatec)
}
})
for more information, you can read this document form MongoDB official website.
Array Update Operators
var checkedBox = req.body.checkbox;
User.updateOne(
{ _id: foundUser._id, "comment._id": checkedBox },
{ $set: { "comment.$.cpermission": 1 } },
function (err, update) {
if (err) {
console.log(err);
} else {
console.log("successfull");
console.log(update);
}
}
);

How to do nested find in mongoose?

I have a user model which has todolists field, in the todolists field I want to get the specific todolist by id. my query is like this:
User.find({_id: user._id, _creator: user, todoList: todoList._id}, 'todoLists') // how do I query for todoList id here? I used _creator this on populate query.
Can I also do a search on a Usermodel field like this?
User.todoLists.find({todoList: todoList._id})
I haven't tested this yet because I am still modifying my Graphql schema and I am new in mongoose.I would really appreciate Links and suggestions. Help?
Assuming your models looks like this:
const todoListSchema = new Schema({
item: { type: String },
}, { collection: 'todolist' });
const userSchema = new Schema({
todoList: [todoListSchema],
}, { collection: 'user' });
mongoose.model('user', userSchema);
mongoose.model('todoList', todoListSchema);
Now you have multiple ways to do that:
1. Using the array filter() method
reference
User.findById(_id, (err, user) => {
const todoList = user.todoList.filter(id => id.equals(tdlId));
//your code..
})
2. Using mongoose id() method
reference
User.findById(_id, (err, user) => {
const todoList = user.todoList.id(tdlId);
//your code..
})
3. Using mongoose aggregate
reference
User.aggregate(
{ $match: { _id: userId} },
{ $unwind: '$todoList' },
{ $match: { todoList: tdlId } },
{ $project: { todoList: 1 } }
).then((user, err) => {
//your code..
}
});

Mongoose remove subdocuments by id method

I have two models:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ProjectSchema = new Schema({
title: { type: String },
images: [{
type: Schema.Types.ObjectId,
ref: 'Image'
}]
});
module.exports = mongoose.model('Project', ProjectSchema);
and
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ImageSchema = new Schema({
fileName: { type: String },
fileSize: { type: Number }
});
module.exports = mongoose.model('Image', ImageSchema);
Existing projects are filled with images as follows:
Project.findById(req.params.project_id, function(err, project) {
if (err) { res.status(400).send(err); }
var image = new Image({
fileName: req.file.name,
fileSize: req.file.size
});
image.save(function(err) {
if (err) { res.status(400).send(err); }
project.images.push(image);
project.save();
);
});
There are no problems in getting images from the project:
Project.findById(req.params.project_id)
.populate('images')
.exec(function(err, project) {
if (err) { res.status(400).send(err); }
res.status(200).json(project.images);
});
i try removing an image from a story, using Mongoose documentation:
http://mongoosejs.com/docs/subdocs.html
http://mongoosejs.com/docs/api.html#types_documentarray_MongooseDocumentArray.id
Project
.findById(req.params.project_id)
.populate('images')
.exec(function(err, project) {
if (err) { res.status(400).send(err); }
project.images.id(req.params.image_id).remove();
project.save();
});
But i keep getting errors:
/api-server/app/admin/images/index.js:170
project.images.id(req.params.image_id).remove();
^
TypeError: project.images.id is not a function
I searched here for solutions, but i only got some things on $pull from 2013.
Is the .id() method broken, or am i doing something wrong.
As i'm fairly new to mongoose, are there ways to do this better?
You just need to delete the image from the database. I hope the following code helps you.
Project
.findById(req.params.project_id)
.exec(function(err, project) {
if (err) { res.status(400).send(err); }
project.save();
Image.remove({"_id":project.images._id},function(){})
});
You can delete subdocuments by using findByIdAndUpdate and $pull.
Seting options to {new: true} overwrites the existing document
var fieldsToRemove= {
$pull: {
images: {
_id: req.params.type
}
}
};
var options = { new: true };
Project.findByIdAndUpdate(req.params.project_id, fieldsToRemove, options,
function(err, project) {...
it will remove the subdocument with specified _id

Auto incrementing field in mongoose

I'm trying to implement an auto incrementing field in mongodb as highlighted in the docs (http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/). However, I'm not exactly sure what is the best way to do so in mongoose.
I have a CounterSchema and a UserSchema, and I'm wondering where to put the getNextSequence function, and how to call it from the User Schema?
//counter.js
var CounterSchema = new Schema({
category: String,
seq: Number
});
//done in mongo shell
db.counters.insert({category: 'userIndex', seq: 0})
//user.js
var UserSchema = new Schema({
name: String,
UserIndex: Number
}
//per mongodb docs -> not sure where I should insert it
function getNextSequence(name) {
var ret = db.counters.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
Try pre save async middleware like this
User.pre('save', true, function(next, done){
var self = this;
var Autoincrement = mongoose.model('Autoincrement');
if (self.isNew){
Autoincrement.getNext(function(err, val){
if (err) return done(err);
self.auto = val;
done();
});
}else{
// done should be called after next
setTimeout(done,0);
}
next();
});

Resources