Mongodb, getting the id of the newly pushed embedded object - mongodb

I have embedded comments in a posts model. I am using mongoosejs. After pushing a new comment in a post, I want to access the id of the newly added embedded comment. Not sure how to get it.
Here is how the code looks like.
var post = Post.findById(postId,function(err,post){
if(err){console.log(err);self.res.send(500,err)}
post.comments.push(comment);
post.save(function(err,story){
if(err){console.log(err);self.res.send(500,err)}
self.res.send(comment);
})
});
In the above code, the id of the comment is not returned. Note there is a _id field which is created in the db.
The schema looks like
var CommentSchema = new Schema({
...
})
var PostSchema = new Schema({
...
comments:[CommentSchema],
...
});

A document's _id value is actually assigned by the client, not the server. So the _id of the new comment is available right after you call:
post.comments.push(comment);
The embedded doc pushed to post.comments will have its _id assigned as it's added, so you can pull it from there:
console.log('_id assigned is: %s', post.comments[post.comments.length-1]._id);

You can manually generate the _id then you don't have to worry about pulling it back out later.
var mongoose = require('mongoose');
var myId = mongoose.Types.ObjectId();
// then set the _id key manually in your object
_id: myId
// or
myObject[_id] = myId
// then you can use it wherever

_id field is generated at client side, you can get the id of the embedded document by comment.id
sample
> var CommentSchema = new Schema({
text:{type:String}
})
> var CommentSchema = new mongoose.Schema({
text:{type:String}
})
> var Story = db.model('story',StorySchema)
> var Comment = db.model('comment',CommentSchema)
> s= new Story({title:1111})
{ title: '1111', _id: 5093c6523f0446990e000003, comments: [] }
> c= new Comment({text:'hi'})
{ text: 'hi', _id: 5093c65e3f0446990e000004 }
> s.comments.push(c)
> s.save()
verify in mongo db shell
> db.stories.findOne()
{
"title" : "1111",
"_id" : ObjectId("5093c6523f0446990e000003"),
"comments" : [
{
"_id" : ObjectId("5093c65e3f0446990e000004"),
"text" : "hi"
}
],
"__v" : 0
}

Related

validate subDocuments in a dictionary in Mongoose

I have a userTasteSchema, with a dictionary field favorites composed by
favoriteSchema objects. When I save or update a userTaste, I want to validate that the elements of the dictionary are valid favorite objects.
Is it possible?
thank you
var userTasteSchema = new Schema(
{
favorites : {type: { /* dictionary of favorites */ }, default:{} }
});
var favoriteSchema = new Schema(
{
name : {type:{String}}
});
You have to change your model declaration. According to the docs your code should look like:
var userTasteSchema = new Schema(
{
favorites : [ favoriteSchema ]
});
var favoriteSchema = new Schema(
{
name : {type:String}
});
And that's pretty much it. When you save your parent document, UserTaste, your children validations are run as well. Here is the reference
Validation is asynchronously recursive; when you call Model#save,
sub-document validation is executed as well. If an error occurs, your
Model#save callback receives it

How to set a default collection in mongoose embedded document schema

How can I set a default collection in a model schema in mongoose. Using the basic example, how can I have for example a default comment in the comments array. e.g.
var defaultComment = {title: 'add your first post'}
do I do something like this in the definition? comments: {type:[Comments], default:defaultComment }
var Comments = new Schema({
title : String
, body : String
, date : Date
});
var BlogPost = new Schema({
author : ObjectId
, title : String
, body : String
, date : Date
, comments : [Comments]
, meta : {
votes : Number
, favs : Number
}
});
mongoose.model('BlogPost', BlogPost);
According to the Mongoose documentation for Schemas, keys may specify a default value. So for your example, one might define the Comments schema as so:
var Comments = new Schema({
title : String
, body : String
, date : Date
});
var CommentsModel = mongoose.model("comments", Comments);
Then, store your default comment, and use it as the default value in your BlogPost schema:
var defaultComment = new CommentsModel({
title: "Add your first post"
});
var BlogPost = new Schema({
author : ObjectId
, title : String
, body : String
, date : Date
, comments : { type: [Comments], default: defaultComment }
, meta : {
votes : Number
, favs : Number
}
});
I hope this helps. Cheers!

Updating Mongoose Subdocument collection

I have the following mongoose Schema's defined...
var BlogSchema = new Schema({
content: String,
comments:[CommentSchema], //embed the comments
owner: {type: ObjectId , ref: 'User'}
})
var CommentSchema = new Schema({
commentContent : String,
commentPostTime : Number,
likes : [{type: ObjectId , ref: 'User'}],
likeCount: {type: Number, default:0}
})
var UserSchema = new Schema({
})
When a user likes a comment. The user should be added to likes list and the embedded Comment Subdocument in Blog Document should be updated. I am not sure how to achieve this.
Help appreciated.
As your UserSchema doesn't contain much information, it's probably simplest if you don't try to fake a join through Mongoose's population feature. Using MongoDB by itself, accomplishing this would be done with a single operation. Below, I'm just storing the "_id" field of some user document that I want to reference.
> var userID = userdoc._id;
> db.comments.update( { _id : commentID },
{ $push : { likes : userID } } );
Doing this with Mongoose would require you to change your schema slightly:
var CommentSchema = new Schema({
commentContent : String,
commentPostTime : Number,
likes : [ObjectId],
likeCount: {type: Number, default:0}
})
Then, you could just add the new user to the list of likes and increment the likeCount field with the following query:
Comment.findByIdAndUpdate( commentID, { $push : { likes : "samantha" }, $inc : { likeCount : 1 } } );
Is this better than using Mongoose population? Handling your data this way will take an extra step when you look up users from comments. First, you'll have to grab the userID from the list of likes in the comment, then you'll have to run a separate query to get that user's document. However, since your use case doesn't appear to require looking anything up in the user documents, this approach should work well for you. Performance-wise, I believe that this two-step process is what Mongoose is doing under the hood anyway with their population method. Personally, I'm fine with the extra lookup step in exchange for more control over my data.

Mongoose/MongoDB - Saving a record to overwrite current data:

So I have a object in the DB that is basically blog posts, there is a array of ObjectID's in there that reference the Categories collection.
So
Posts = {
title: String,
Content: String,
Categories: [{
type: ObjectID,
ref: 'Categories'
}]
I can create the posts fine, problem comes when I try to update them:
post.title = 'hi';
post.content = 'content';
post.categories = ['44523452525','4e1342413421342'];
post.save(function(){});
For some reason it will ADD those 2 categories instead of wiping the categories array and inserting those.
How do I get it to remove those and insert new ones?
I tried to reproduce this behavior but I couldn't - here's the code sample I ran:
var mongoose = require('mongoose')
var Schema = mongoose.Schema
mongoose.connect('mongodb://localhost/testjs');
PostSchema = new Schema({
title:String,
content:String,
cats:[]
});
var Post = mongoose.model('Post', PostSchema);
var mypost = new Post()
mypost.title = "x"
mypost.content = "y"
mypost.cats = ['a','b','c']
mypost.save(
function(err){
mypost.cats = ['d','e']
mypost.save()
}
);
After the second call to save() the array contains only what it was set to ("d","e"). Can you try it and see if you get the same result? Maybe it's related to mongoose version, or something.

How do I get data out of Mongo using Mongoose?

Running into problems getting any data out of mongo using mongoose. The connection seems fine as i've got debugging statements that are being printed out. I've searched high and low for what could be causing this but afaik I'm setting up the schema and collections fine.
here's what i have in a file called posts.js:
var mongoose = require('mongoose');
var db = mongoose.connect('mongodb://localhost:27017/sister', function(err) {
if (err) throw err;} //this does not get printed
);
mongoose.connection.on("open", function(){
console.log("mongodb is connected")} //this gets printed
);
var Schema = mongoose.Schema;
var thePost = new Schema({
name : String
});
mongoose.model('post', thePost);
var posts = db.model('post');
posts.find({}, [], function(err, calls) {
console.log(err, calls, calls.length); //prints out: null [] 0
});
To seed the data, I've done this in my mongo shell, which inserts a document and then shows that find all can find it:
> randumb = { name : 'emile' };
{ "name" : "emile" }
> db.post.insert(randumb);
> db.post.find({});
{ "_id" : ObjectId("4e775e8cc24f31883fdafbab"), "name" : "emile" }
try changing
var posts = db.model('post');
to
var posts = mongoose.model('post');
To keep it even shorter, try and change:
mongoose.model('post', thePost);
var posts = db.model('post');
to:
var posts = mongoose.model('post', thePost);