MongoDB - how do I deep populate, an already populated field that has a reference to the schema it is in? - javascript

So I am having the following problem, I have a comments schema, which has a field called Replies and it is pointing toward the comment schema. The problem is that whenever I try to populate the following schema, everything except for the replies gets populated. Why is that happening, how do I fix it?
Comment Schema:
const {Schema, model} = require('mongoose')
const { ObjectId } = require('mongodb');
const commentSchema = new Schema({
Author:
{
type: ObjectId,
required: true,
ref: 'user'
},
Content:
{
type: String,
required: true
},
Likes:{
type: [ObjectId],
ref: 'user'
},
Replies: [this]
})
let comment = model('comment', commentSchema)
module.exports = comment
And that is how I populate the posts model:
let allPosts = await postModel
.find({})
.populate('Author Comments')
.populate(
(
{
path: 'Comments',
populate:[
{path: 'Author'}
]
},
{
path: 'Comments.Replies',
populate:[
{path: 'Author'}
]
}
)
)
and this is my post model, referenced in the previous code sample:
const {Schema, model} = require('mongoose')
const { ObjectId } = require('mongodb');
const postSchema = new Schema({
Author:
{
type: ObjectId,
required: true,
ref: 'user'
},
Content:
{
type: String,
required: true
},
Shares:{
type: [ObjectId],
ref: 'post'
},
Likes:{
type: [ObjectId],
ref: 'user'
},
Comments:{
type: [ObjectId],
ref: 'comment'
}
})
let post = model('post', postSchema)
module.exports = post

Related

Pushing object to triple nested array in Mongoose

I am trying to figure out how to access and push an object into a triple nested array while using mongoose.
My idea is to divide a blog post into an array of chapters, where each has their own array of pages. Each page will have a title, image and body.
Story schema (parent document)
const mongoose = require('mongoose')
const pageSchema = require('./pageModel')
const storySchema = mongoose.Schema({
storyTitle: {
type: String,
required: [true, 'Title required.']
},
storyAuthor: {
type: String,
required: [true, 'Author required.']
},
storyImage: {
type: String,
required: true,
},
chapters: [{
chapterTitle: {
type: String,
//required: [true, 'Title required.']
},
chapterSummary: {
type: String,
// required: [true, 'Summary required.']
},
pages: [pageSchema]
}]
})
module.exports = mongoose.model('Story', storySchema)
the Page Schema
const mongoose = require('mongoose')
const pageSchema = mongoose.Schema({
pageTitle: {
type: String,
required: [true, 'Title required.']
},
pageBody: {
type: String,
},
pageImage: {
type: String,
}
})
module.exports = pageSchema;
Simple ops
const mongoose = require('mongoose')
const Story = require('./storyModel')
const Page = require('./pageModel')
const test = new Story({
storyTitle: 'Test',
storyAuthor: 'Myself',
storyImage: 'test',
});
console.log(test);
test.chapters.push({
chapterTitle: 'chapter 1',
chapterSummary: 'let us see',
})
const first = {
pageTitle: 'A page',
pageImage: 'image',
pageBody: 'A body'
}
console.log(test)
//test.chapters[0].pages[0].push(page)
test.chapters[0].pages.push(first)
console.log(test)
When I log each step, the parent is correctly made, and I am able to append a chapter to the chapters array. But when I the first object, the change isn't visible.
If I log test.chapters, the pages array shows pages: [ [Object] ]
And if I log test.chapters.pages, I just see 'undefined'.
Any suggestions and critique is appreciated.

changing array inside the collection mongoDB

I am trying to change an array in my collection of users according to the id of an object I have in my array
it looks like this
_id:60a54bb0a5c5d25c9f4b83ea
email:"timotej"
pass:"$2b$10$hdvMb.PrcRmwNCqxcLpOmOLTvRTrMzHWAhPHWa4o4E.qOfuDTjeAm"
createdAt:2021-05-19T17:32:32.792+00:00
updatedAt:2021-05-23T11:32:37.882+00:00
__v:0
contacts:Array
0:Object
_id:"60aa3d3db9344014e5944291"
name:"contact1"
email:"contact1#mail.com"
phone:"0"
1:Object
_id:"60aa3d55b9344014e5944292"
name:"contact2"
email:"contact2#mail.com"
phone:"00"
Shema:
const mongoose = require('mongoose')
const Schema = mongoose.Schema;
const userSchema = new Schema({
email: {
type: String,
required: true,
unique: true
},
pass:{
type: String,
required: true
},
contacts:{
_id: {
type: String,
unique: true
},
name:{
type: String,
},
email:{
type: String
},
phone:{
type: String
}
}
}, {timestamps: true})
const User = mongoose.model('User', userSchema)
module.exports = User;
here is my code, I am trying to find the user by its email, and then the object in array contacts by its id and then update the contact.
const user = User.findOneAndUpdate(
{ email: mail.toLowerCase(), "contacts._id": req.params.id},
{ $set:{
"contacts.$._id": req.params.id,
"contacts.$.name": req.body.name,
"contacts.$.email": req.body.email,
"contacts.$.phone": req.body.phone,
}
},
{ multi: false }
).then((result) => {
console.log("result : " + result)
the data in req should be ok, but nothing is changing in my db when i send request

Mongo populate in optional field giving cast error

I have a 'vendor' and 'media' collection, media collection store vendor profile images and that is not mandatory field for vendors. Some vendors have profile picture some not, I want to list all vendors including their profile pictures reference. But I'm getting cast error when I populate profilePicture from meidas. I have other populate like 'userId', 'venueId' those are mandatory fields and it works.
Error:
CastError: Cast to ObjectId failed for value "xyz" at path "_id" for model "medias" undefined
Find Query:
const result = await resultObject.skip(skip)
.populate('userId')
.populate('venueId')
.populate('profilePicture')
.limit(parseInt(obj.pageSize, 10))
.sort({ [obj.sortColumn]: parseInt(obj.sortValue, 10) });
return result;
medias model
const MediasModel = () => {
const MediasSchema = new mongoose.Schema({
url: { type: String, required: true },
key: { type: String},
}, { timestamps: { createdAt: 'createdDate', updatedAt: 'modifedDate' } });
return mongoose.model('medias', MediasSchema);
};
module.exports = MediasModel();
vendors model
const Vendors = new mongoose.Schema({
venueId: { type: mongoose.Schema.Types.ObjectId, ref: 'venues' },
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'users' },
name: { type: String, required: true },
profilePicture: { type: mongoose.Schema.Types.ObjectId, ref: 'medias' },
}, { timestamps: { createdAt: 'createdDate', updatedAt: 'modifedDate' } });
module.exports = mongoose.model('vendors', Vendors);
Try the below code
const Vendors = require('path/to/model_vendor');
Vendors.find()
.populate([{path: 'venues'}, {path: 'users'}, {path: 'medias'}])
.skip(skip_value)
.limit(limit_value)
.sort({condition: 1 }) // Modify according to your need
.exec().
.then(vendors=>{
console.log(vendors)
}).catch(err=>{
console.log(err)
})

How can I limit the returned items from a Mongoose array populate?

I have a model that we use for a conversational chat, that uses nested arrays. Each time a user sends a message, it gets pushed into the messages array. This is my model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ConversationSchema = new Schema({
sender: {
type: Schema.Types.ObjectId,
ref: 'User'
},
messages: [
{
message: String,
meta: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
delivered: Boolean,
read: Boolean
}
]
}
],
is_group_message: { type: Boolean, default: false },
participants: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
delivered: Boolean,
read: Boolean,
last_seen: Date
}
]
}, { timestamps: true });
module.exports = mongoose.model('Conversation', ConversationSchema);
I'm trying to find all conversations, that a user is a part of, but I'm unable to return only the most recent chat message, and it seems to ignore the options. Is this a model or populate issue on my end?
Conversation.find({ 'participants.user': { $all: [req.user._id] } })
.sort('-createdAt')
.populate({
path: 'sender',
select: '-_id -password -email -lastLogin -createdAt -updatedAt -__v',
})
.populate({
path: 'messages.meta.user',
select: 'username avatar',
options: {
limit: 1
}
})
.populate({
path: 'participants',
path: 'participants.user',
select: 'username avatar'
})
.then(conversation => {
if (!conversation) {
errors.noconversation = 'No conversation could be found';
return res.status(404).json(errors);
}
res.json(conversation)
})
.catch(err => res.status(404).json({ conversation: 'There are no conversations or an error occurred' }));

Mongoose population

I have this Mongoose Schema
var ItemSchema = new Schema({
"name":String,
"review": [{ type: Schema.Types.ObjectId, ref: 'Reviews'}]
});
and the schema of the review is:
var ReviewSchema = new Schema({
"title": String,
"user": { type: Schema.Types.ObjectId, ref: 'Users' }
});
and the schema of the users is:
var UserSchema = new Schema({
"name":String,
"surname":String,
});
This is the code to get the item:
Item.findOne({_id:req.params.idItem})
.populate('review')
.exec(function (err, item) {
console.log(item);
});
But this code only populates the reviews, and I want that to populate also the user.
Item.findOne({_id:req.params.idItem})
.populate({
path: 'review',
populate: {
path: 'user'
}
})
.exec(function(err, item) {});
http://mongoosejs.com/docs/populate.html#deep-populate

Categories

Resources