How to set a default collection in mongoose embedded document schema - mongodb

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!

Related

Delete mongo recored by the timestamp in its id

This question is mostly popular but with a slight twist; I need to delete few records by when it was created, using its _id. I do not have any date, createdAt fields as I see that mongo uses its _id for the createdAt timestamp.
How do I delete a recored, say created 30 days ago, using this gist?
const date = new Date();
const daysToDeletion = 30;
const deletionDate = new Date(date.setDate(date.getDate() - daysToDeletion));
const db = <your-database>
db.messages.remove({_id : {$lt : deletionDate}});
The above returns a CastError
What would work, and as Ive said, I do not have a createdAt field:
db.messages.remove({createdAt : {$lt : deletionDate}});
Use mongo shell:
db.collection.find({"_id": { "$gt": ObjectId.fromDate(new Date('2017-10-01'))}})
Use mongoose:
Model.find({ _id: { $gt: mongoose.Types.ObjectId.createFromTime(new Date('2018-01-01')) } })
will find the needed docs.
var id = new ObjectId( Math.floor(deletionDate .getTime() / 1000).toString(16) + "0000000000000000")
db.messages.remove({createdAt : {$lt : id}});
You need to extract the timestamp from the object _id. So you could do something like:-
db.messages.find({}).forEach(function(rec) {
var recDate = rec._id.getTimestamp();
// Then here cast your deletionDate and recDate to preferred string format, e.g:-
var recDateString = recDate.getMonth()+1+'-'+recDate.getDate()+'-'+recDate.getFullYear();
var deletionDateString = deletionDate.getMonth()+1+'-'+deletionDate.getDate()+'-'+deletionDate.getFullYear();
if (deletionDateString == recDateString ){
db.messages.remove({_id:rec._id});
}
}

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.

Mongodb, getting the id of the newly pushed embedded object

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
}

Filling a form (caolan) with default values in node.js

I am using caolan forms with node.js. My schema looks like:
var News = new Schema({
name : String
, index: Number
});
My form has 3 news fields:
var news = forms.create({ news_1: fields.string({required: true}),
news_2: fields.string({required: true}),
news_3: fields.string({required: true})
});
I now try to fill this form with default values which is where I need help. What am I doing wrong in the following code?
news.bind({news_1: "test1", news_2: "test2", news_3: "test3"});
Thanks.
You can create form with this object
{
news_1: fields.string({required: true, value : 'test1'}),
news_2: fields.string({required: true, value : 'test2'}),
news_3: fields.string({required: true, value : 'test3'})
}

How can I search an embedded collection within MongoDB?

For example suppose I have a Post schema as follows:
var Schema = new db.Schema({
title : String
, text : String
// Denormalize by using user name
, author : String
, tags: [String]
, comments: [Comment]
});
I'm trying to match a particular tag as follows:
function getPostByTag(tag, callback) {
Post.find().where({"tags.value": tag}).run(callback);
}
But it is returning everything. What am I doing wrong?
Where are you getting the "value" part of "tags.value". Shouldn't it just be:
Post.find().where({tags:tag}).run(callback);