Populate document if there is no value, using MongooseJS - javascript

Let's say I have a User model like this
var userSchema = new Schema({
username : String,
email : String,
project : {type : String, ref : "Project"}
});
and a User document like this.
{
"_id" : ObjectId("56df56c58a4d47c83bf41603"),
"username" : "user1",
"email" : "email#example.com",
"project" : "",
"__v" : 1
}
If I do the following, the page never loads.
User.findById("56df56c58a4d47c83bf41603").populate("project").exec()
.then(function(userObj) {
res.render('user', {
user : userObj
});
});
It works fine if there is an actual ObjectID in there, but not when it is blank.
Is there a way that I can default to null if there is no ObjectID in the value?

So the answer to the question is here:
Mongoose: CastError: Cast to ObjectId failed for value "[object Object]" at path "_id"
An empty string will throw a cast error. Your weren't trapping the exception from the promise based call and so your route was timing out.
The lesson is to trap the exception. Just like you would if you were using callbacks.

Related

MongoDB query work but not with Mongoose

I'm trying to query a collection with Mongoose, there is the collection sample output with a simple db.course.find() query
{
"_id" : ObjectId("581c9408fc01b15cb21043e4"),
"calendar_id" : DBRef("calendar", ObjectId("581c5972fd1c59295c34f1b8"), "ecampus"),
"date" : 1478473200000,
"title" : "Conception et planification BI",
"teacher" : "fiolet gilles",
"start_at" : "08:30",
"end_at" : "12:30"
}
I have a MongoDB query that work well
db.course.find({'calendar_id.$id': ObjectId("581c5972fd1c59295c34f1b8")}).sort({date: 1})
I am trying to do the same query with Mongoose, in my NodeJS app
I made this query but this one return an empty array because the ObjectId is not working well.
let mongoose = require('mongoose');
let ObjectId = mongoose.Types.ObjectId;
let id = new ObjectId(session.calendar_id);
Course.find({'calendar_id.$id': id}).sort({date: 1}).exec(function (err, courses) {
console.log(err, courses);
createJsonBody(courses);
});
Course is from my model file and is like this
const Course = mongoose.model('course', {
calendar_id: Schema.ObjectId,
date: Number,
title: String,
teacher: String,
start_at: String,
end_at: String
});
How can I make this Mongoose query to work ? The model is maybe not properly formed ?
Use Course.find({'calendar_id': id}) instead of Course.find({'calendar_id.$id': id}).
For mongoose $id does not exist.

node and mongo:retrieval of documents using array of ids

i have two collections.
1)notifications
2)forums
the schemas for these collections are present in seperate js files notifications.js and forum.js as the following
notifications.js
var mongoose = require("mongoose");
var notificationSchema = new mongoose.Schema(
{
username: String,
message: String,
date: Date,
deleted: String,
commentids: [{id:String}]
});module.exports = mongoose.model('notifications', notificationSchema);
forum.js
var mongoose = require("mongoose");
var notificationSchema = new mongoose.Schema(
{
username: String,
message: String,
date: Date,
deleted: String,
commentids: [{id:String}]
}); module.exports = mongoose.model('notifications', notificationSchema);
forums collection looks like this:
{ "_id" : ObjectId("5751e2b315cdbc58164df7cd"),
"notificationids" : [
ObjectId("5751e2be15cdbc58164df7d0"),
ObjectId("5751e2c415cdbc58164df7d1")
],
"__v" : 0
}
notificationids is an array in forums collection which stores the ids of corresponding notifications.
and notifications collection looks as shown below
{
"_id" : ObjectId("5751e2be15cdbc58164df7d0"),
"username" : "ab",
"message" : "hello",
"date" : ISODate("2016-06-03T20:04:14.487Z"),
"deleted" : "false",
"commentids" : [ ],
"__v" : 0
}
{
"_id" : ObjectId("5751e2c415cdbc58164df7d1"),
"username" : "ab",
"message" : "how are you",
"date" : ISODate("2016-06-03T20:04:20.769Z"),
"deleted" : "false",
"commentids" : [ ],
"__v" : 0
}
now i have to write a query in mongoose to select all the "notifications" documents whose "_id"s are present in the notificationids array of forums collection.
i.e, since here notificationids=[ ObjectId("5751e2be15cdbc58164df7d0"),
ObjectId("5751e2c415cdbc58164df7d1")],
the query must return all the documents of notifications collection as ids
5751e2be15cdbc58164df7d0 and 5751e2c415cdbc58164df7d1 are present in notifications collection
i have written a file server.js like this in nodejs..
server.js
var ForumModel = require('../models/forum');
var NotificationModel=require('../models/notifications');
var mongoose=require("mongoose");
ForumModel.find({_id:"5751e2b315cdbc58164df7cd"},function(err,data)
{
if(err)
{
console.log("couldnot load the group forum");
}
else
{
console.log("forum notificationids are"+data);
//the below query returns result as empty
NotificationModel.find({'_id':{$in:data}},function(err,result)
{
if(err)
{
console.log("couldnot load notifications "+err);
}
else
{
console.log("notifications are sent to the clientand result is"+result);
}
});
}
the output of the above code when run is :
forum notification ids are
{ notificationids: [ 5751e2be15cdbc58164df7d0,
5751e2c415cdbc58164df7d1 ],
__v: 0,
_id: 5751e2b315cdbc58164df7cd
}
notifications are sent to the client and result is
As you can clearly see result is empty. i duno where i am doing wrong. i tried casting notificationids array elements to ObjectIds using
notificationids.map(function(o){return mongoose.Types.ObjectId(o);});
But this,as expected gave an error :
mongoose.Types.ObjectId error "Argument passed in must be a single String of 12 bytes or a string of 24 hex characters");
I also tried storing the objectids as strings but that dint work too.
thanks in advance.

Mongoose: Finding a user in a collection and checking if this user's array contains x?

I have a collection called 'users' where a typical user entry looks something like this:
{
"__v" : 0,
"_id" : ObjectId("536d1ac80bdc7e680f3436c0"),
"joinDate" : ISODate("2014-05-09T18:13:28.079Z"),
"lastActiveDate" : ISODate("2014-05-09T18:13:48.918Z"),
"lastSocketId" : null,
"password" : "Johndoe6",
"roles" : ['mod'], // I want this to be checked
"username" : "johndoe6"
}
I want to create an if function that finds a user variable targetuser, and checks to see if his 'roles' array contains a 'mod'.
How can this be done with mongoose?
It can be done easily. Code below describes in detail what must be done to achieve this.
Steps:
get mongoose module
connect to mongo and find the right database
make a schema of your collection (in this case only users)
add a custom method that returns true if the role 'mod' exists in the array. Note: mongo collection doesn't have structure, so it might be good to run a check if the property 'roles' exists and it is an array.
model the created schema.
test it by finding random (one) document/user and check if it is a moderator.
So, this is programmed as:
// get mongoose.
var mongoose = require('mongoose');
// connect to your local pc on database myDB.
mongoose.connect('mongodb://localhost:27017/myDB');
// your userschema.
var schema = new mongoose.Schema({
joinDate : {type:Date, default:Date.now},
lastActiveDate: Date,
lastSocketId : String,
username : String,
password : String,
roles : Array
});
// attach custom method.
schema.methods.isModerator = function() {
// if array roles has text 'mod' then it's true.
return (this.roles.indexOf('mod')>-1);
};
// model that schema giving the name 'users'.
var model = mongoose.model('users', schema);
// find any user.
model.findOne({}, function(err, user)
{
// if there are no errors and we found an user.
// log that result.
if (!err && user) console.log(user.isModerator());
});

Nested Arrays in Mongoose with ObjectId

I am trying to record the id's of the posts that the user has voted on, and I am creating a schema for it like this:
var userSchema = new Schema({
twittername: String,
twitterID: Number,
votedPosts: [{ObjectId : {votetype : Number}} ]
});
The user gets created perfectly and I want to update the votedPosts attribute whenever the user votes on something so I call :
User.update({twitterID : req.body.userID} , { $push : {votedPosts : {postID : {votetype: newvotetype }}}} ,function (err, user, raw) {
if (err){
console.log(err);
}
else{
console.log('user ' + user);
}
});
Unfortunately the outcome is not as I described in my schema, I get this:
db.users.find().pretty()
{
"__v" : 0,
"_id" : ObjectId("51bf4ef8dbda2f2e0c000001"),
"twitterID" : 102016704,
"twittername" : "gorkemyurt",
"votedPosts" : [
{
"_id" : ObjectId("51bf5e48c3ffefe20c000002")
}
]
}
I am confused by the extra "_id" that mongoose adds in the votedPosts array.. Why cant ObjectId("51bf5e48c3ffefe20c000002") be the key of a key value pair?
I think your problem stems from your schema. You should try to define a schema in which the keys are not dynamically changing. MongoDB does not support queries on the keys of documents, just the values.
I think that using a dynamic "ObjectID" as the key in your schema above is leading to weirdness with Mongoose, and causing your issue. But, even if your query were propagated properly to MongoDB, it would still not produce the output you desire. The reason for this is that MongoDB will interpret "postID" as a String, regardless of whether you've defined some postID variable to hold a dynamic value. This is the output if you run the query from the mongo shell, using a variable postID:
> var postID = 1234
> db.users.update( {twitterID : 102016704}, {$push : {votedPosts : {postID : {votetype: "newvotetype" }}}} )
{
"__v" : 0,
"_id" : ObjectId("51bf4ef8dbda2f2e0c000001"),
"twitterID" : 102016704,
"twittername" : "gorkemyurt",
"votedPosts" : [
{
"postID" : {
"votetype" : "newvotetype"
}
}
]
}
I would suggest that you use another schema. The schema I've proposed below involves embedding a second schema into your existing schema. Try something like this:
var votedPost = new Schema({
postID: ObjectId,
votetype : Number
});
var userSchema = new Schema({
twittername: String,
twitterID: Number,
votedPosts: [votedPost]
});
This way, you can also query on the postID field, which MongoDB handles very nicely. Does that make sense? :)

mongodb won't find my schema method in nested container

I am trying to access the method of a schema which is stored inside a mixed container. Here is the situation :
I have some cases model which can be many different things, so I have a schema for each of these things which are stored in the "caseContent" mixed property.
var CaseSchema = mongoose.Schema({
caseContent : {},
object : {type:String, default : "null"},
collision : {type : Boolean, default : false}
});
The caseContent property is then filled with the model of one of my schemas, like this one for exemple :
var TreeSchema = new mongoose.Schema({
appleCount : {type : Number, default : 3}
});
TreeSchema.methods.doStuff = function (data) {
console.log('Hey, listen');
return true;
};
Then, I want to use the method of my schema from the original container :
CaseSchema.methods.doStuff = function (data) {
if (this.caseContent.doStuff !== undefined) {
this.caseContent.doStuff();
console.log('it worked');
} else {
console.log('doStuff is undefined');
console.log(this.caseContent.doStuff);
}
};
On the first time (when everything is added on the database) it works. Then, the caseContent.doStuff seems to be always undefined (the console.log('doStuff is undefined'); appears each time).
So I think there is something that keeps me from calling that method probably because of the mixed type of the container... Is there any workarround for that ?
You could try to use this schema type Schema.Types.Mixed
var CaseSchema = mongoose.Schema({
caseContent : Schema.Types.Mixed,
object : {type:String, default : "null"},
collision : {type : Boolean, default : false}
});

Categories

Resources