Can't get mongoose 'populate' to work - node.js

I am stuck on populating a ref field in a simple mongoose (3.8.8) query.
It's probably a stupid issue but i can't actually sort it out..
var Schema = mongoose.Schema;
var ItemSchema = new Schema({
description: { type: String },
comments: [ { type:Schema.Types.ObjectId, ref:'Comment'} ],
created: { type: Date, default: Date.now }
});
var Item = mongoose.model('Item', ItemSchema);
var CommentSchema = new Schema({
text: { type: String },
item_id: { type:Schema.Types.ObjectId, ref:'Item'} ,
created: { type: Date, default: Date.now }
});
var Comment = mongoose.model('Comment', CommentSchema);
Item.find().populate('comments').exec(function(err,item){
console.log('Item ',item)
})
the data is:
/* item0 */
{
"_id" : ObjectId("53da00cc5ddd29442463e716"),
"description" : "item1",
"created" : ISODate("2014-07-31T08:39:40.475Z"),
"comments" : [],
"__v" : 0
}
/* item1 */
{
"_id" : ObjectId("53da00cc5ddd29442463e717"),
"description" : "item2",
"created" : ISODate("2014-07-31T08:39:40.478Z"),
"comments" : [],
"__v" : 0
}
/* comment0 */
{
"_id" : ObjectId("53da01e9ef4ecaa0231fdc8d"),
"item_id" : ObjectId("53da00cc5ddd29442463e716"),
"text" : "comment1",
"created" : ISODate("2014-07-31T08:44:25.768Z"),
"__v" : 0
}
It just won't work as expected, not populating the 'comments' array, tho in my comments collection the item_id is populated correctly.
What's the problem?
Thanks in advance

Related

how to create a mongoose model with list of dictionaries?

I am trying to create a model for a collection whose objects look like below,how do declare clonedChangesdetailslist in mongoose which is a list of dictionaries?[String] doesn't seem to be the right thing?
{
"_id" : ObjectId("6d17d2dd84d4734eea82989f"),
"orgChange" : "62369696",
"created_on" : ISODate("2019-06-29T14:06:20.686Z"),
"clonedChangesdetailslist" : [
{
"clonedChange" : "62392779",
"clonedStatus" : "PASS",
"clonedChangeFinalStatus" : "PASS",
"updatedFailedReason" : "N/A",
"clonedChangeFinalStatusReason" : "N/A",
"updateStatus" : "PASS",
"clonedStatusfailReason" : "N/A"
},
{
"clonedChange" : "62392793",
"clonedStatus" : "PASS",
"clonedChangeFinalStatus" : "PASS",
"updatedFailedReason" : "N/A",
"clonedChangeFinalStatusReason" : "N/A",
"updateStatus" : "PASS",
"clonedStatusfailReason" : "N/A"
}
]
}
mongodb model
const mongoose = require('mongoose');
const { Schema } = require('mongoose');
const change_cloning_Schema= new Schema({
orgChange: String,
created_on: String,
clonedChangesdetailslist:[String]
},
{
collection: 'change_cloning',
timestamps: { createdAt: true, updatedAt: true },
});
module.exports = mongoose.model('change_cloning', change_cloning_Schema);
You can define clonedChangesdetailslist as an Array of Objects.
Try this :
const change_cloning_Schema= new Schema({
orgChange: String,
created_on: String,
clonedChangesdetailslist:[{
clonedChange : String,
clonedStatus : String,
clonedChangeFinalStatus : String,
updatedFailedReason : String,
clonedChangeFinalStatusReason : String,
updateStatus : String,
clonedStatusfailReason : String
}]
},
{
collection: 'change_cloning',
timestamps: { createdAt: true, updatedAt: true },
});

Mongoose TTL not working on Timestamps

I have issue getting mongoose timestamps work with mongoose expires. I see no MongoDB TTL Index on updatedAt.
schema:
const AdminSessionSchema = mongoose.Schema({
UID: String,
device: String,
updatedAt : { type: Date, expires: 60 }
}, { collection: 'admin.session', timestamps: true });
mongoshell:
> db.admin.session.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "development.admin.session"
}
]
Is this the right way to make it work? or am I missing something.

Inserting products to subschema taking long time?

I have mongoose schema:
var productSchema = new Schema({
"productId" : {type : String},
"productName" : {type : String},
"mrp" : {type : String}
});
var shopSchema = new Schema({
"ShopId" : {type : Number},
"Name" : {type : String},
"contact" : {type : Number},
"products" : [productSchema]
},{collection:"shopProductDetails"});
module.exports.Shops = mongoose.model('Shops',shopSchema);
module.exports.Products = mongoose.model('Products',productSchema);
I inserted data into the shop successfully .Next I have to insert data into the sub schema that is productSchema
Insertion Data
{
"ShopId":"439",
"products": [{
"productId": "1234",
"productName": "non veg",
"mrp": "38",
}, {
"productId": "5678",
"productName": "veg",
"mrp": "38 "
},{...}]
}
Products Insertion Code:
model.Shops.findOne({"ShopId":439},function(err, doc){
if(doc == null){
res.json({'success':'0','result':{},'errorMessage':'Credentials not matched'});
}
else{
async.each(products,function(item){
var insertProducts={productId: item.productId, productName: item.productName, mrp: item.mrp};
doc.products.push(insertProducts)
});
doc.save(function (err, data) {
if (err) {
res.json({'errorMessage':err});
}
else {
res.json({'success':'1','result':{'message':'Products Inserted Successfully'},'errorMessage':'No'});
}
});
}
});
Here the products are inserted successfully, the problem is that it is taking a large time when there is a bulk data. I am using async here,i think its wrong.Can any one suggest a better approach
I would suggest you only having the reference id for the product in the shop. It will save you time when making the query (now you just have to insert an id instead of looking up for another document in the database).

How to update Reference Array in mongoose

I have a Group Collection, which is having a Reference array of Members. Two Objects are inter-connected like follow. When I am adding new members to the group the members field of Group object needed to be updated. How can I do this with a mongoose update operator.
var MemberSchema = new Schema({
name:{
type:String,
default:null
},
user_id:{
type : Schema.ObjectId,
ref : 'User',
default : null
}
});
var GroupSchema = new Schema({
name:{
type:String,
default:null
},
description:{
type:String,
default:null
},
members:[MemberSchema],
},{collection:"groups"});
Thank You in advance.
Update
I added a sample document of group.
{
"_id" : ObjectId("586a2e694467c41218b302c3"),
"members" : [
{
"_id" : ObjectId("586a2e694467c41218b302c6"),
"user_id" : ObjectId("58171d75e72bf516f92dcd4e"),
"name" : "Lakmal Kapukotuwa"
},
{
"_id" : ObjectId("586a2e694467c41218b302c5"),
"user_id" : ObjectId("5821807516325e127f59438e"),
"name" : "Prasad Perera"
},
{
"_id" : ObjectId("586a2e694467c41218b302c4"),
"user_id" : ObjectId("586263515356e908de6c899a"),
"name" : "Sadun Prasad"
}
],
"description" : "Des 1",
"name" : "My group",
"__v" : 0
}
If you are sending the new members as a list of objects with the following structure e.g.
membersListToAdd = [
{
"user_id": "58171d75e72bf516f92dcd4e",
"name": "foo"
},
{
"user_id": "5821807516325e127f59438e",
"name": "bar"
}
]
then use $push with $each modifier in an update as follows:
var query = { name: 'My Group' },
options = {},
callback = function (err, result) { console.log(result); };
Group.update(query, { $push: { members: { $each: membersListToAdd } } }, options, callback)
You are doing this wrong,
no need to have links in both collections and no need to nest models
try this instead
var Group = mongoose.model("Group", new Schema({
name: {
type:String
},
description: {
type:String
},
}));
Group.virtual("users", {
ref: "User",
localField: "_id",
foreignField: "groups"
});
var User = mongoose.model("User", new Schema({
name:{
type:String
},
groups: [{
type : Schema.ObjectId,
ref : 'Group'
}]
}));

How to effectively fetch comments for posts with MongoDB/mongoose?

I have the following Post and Collection documents:
// posts
{
"_id" : ObjectId("56978d8cdbc511a81e7e2ea8"),
"body" : "Post body 1",
"created_at" : 1452772748737
},
{
"_id" : ObjectId("56978d3cdbc655b81e7e2e10"),
"body" : "Post body 2",
"created_at" : 1452772759731
}
// comments
{
"_post" : ObjectId("56978d8cdbc511a81e7e2ea8"),
"body" : "Comment 1"
},
{
"_post" : ObjectId("56978d3cdbc655b81e7e2e10"),
"body" : "Comment 2"
}
I need to query all posts with all comments to be the following result:
{
"_id" : ObjectId("56978d8cdbc511a81e7e2ea8"),
"body" : "Post body 1",
"created_at" : 1452772748737,
"comments": [{
"_post" : ObjectId("56978d8cdbc511a81e7e2ea8"),
"body" : "Comment 1"
}]
},
{
"_id" : ObjectId("56978d3cdbc655b81e7e2e10"),
"body" : "Post body 2",
"created_at" : 1452772759731,
"comments": [{
"_post" : ObjectId("56978d3cdbc655b81e7e2e10"),
"body" : "Comment 2"
}]
}
My schema for post and collections look the following:
// post
var PostSchema = mongoose.Schema({
},{
strict: "throw",
collection: "posts"
});
PostSchema.add({
created_at: {
type: Number,
'default': Date.now
}
});
PostSchema.add({
title: {
type: String
}
});
PostSchema.add({
body: {
type: String
}
});
// comment
var CommentSchema = mongoose.Schema({
},{
strict: "throw",
collection: "comments"
});
CommentSchema.add({
_post: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}
});
CommentSchema.add({
body: {
type: String
}
});
What is the effectively way to get the result above?
Try to do it through mongoose populate and aggregate. Sample codes as below.
var Post = mongoose.model('Post', PostSchema);
var Comment = mongoose.model('Comment', CommentSchema);
Comment.aggregate([
{$group: {_id: '$_post', comments: {$push: '$body'}}}
// ...
], function(err, result) {
if (err)
// error handling
Post.populate(result, {path: "_id"}, function(err, ret) {
if(err)
console.log(err);
else
console.log(ret);
});
});

Resources