Update Sub Sub Array item in MongoDB - node.js

I'm trying to update Sub-Sub Array item in MongoDB. I want to update the Comments(Comment field) inside the Slides array.
Slides--> Comments--> comment
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var AttachmentSchema = new Schema({
FileName: String,
InternalName: String,
FileType: String,
InternalName: String
});
mongoose.model('Attachment', AttachmentSchema);
var SessionSchema = new Schema({
SessionTitle: String,
Chairperson: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
StartDateTime: { type: Date, required: true },
Duration: Number,
Attendees: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
AcceptOrReject: {
Comment: String,
Reason: String,
CreatedDate: Date,
UserId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
Status: String
},
Slides: [{
Seq: Number,
Details: String,
attachement: AttachmentSchema,
TarasulLetterDetails:{
MailObjectId: String,
Description: String,
Subject: String,
TarasulLetterUrl: String
},
Comments: [{
Comment: String,
DateTime: Date,
UserId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
IsFromOnline : String
}],
SurfaceAttachement: [{
FileName: String,
InternalName: String,
FileType: String,
}]
}],
Status: String,
CreatedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
CreatedDate: { type: Date, required: true },
ModifiedDate: Date,
SentDate: Date,
Comments: [{
Comment: String,
DateTime: Date,
UserId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
}],
Notifications: [{
UserId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
CreatedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
AlertType: String,
AlertMessage: String,
DateTime: { type: Date, required: true },
IsAcknowledged: Boolean
}]
});
mongoose.model('Session', SessionSchema);
Below is the sample data.
> db.sessions.find({"_id": ObjectId('5af7bcdff107cb7a105243f5')}).pretty();
{
"_id" : ObjectId("5af7bcdff107cb7a105243f5"),
"SessionTitle" : "Project Status Meeting",
"Duration" : 60,
"StartDateTime" : ISODate("2018-05-15T05:15:00Z"),
"CreatedBy" : ObjectId("5aead4431a7ecc7230fb249a"),
"Status" : "APPROVED",
"CreatedDate" : ISODate("2018-05-13T04:19:43.050Z"),
"Notifications" : [
{
"IsAcknowledged" : false,
"DateTime" : ISODate("2018-05-14T09:15:23.385Z"),
"AlertMessage" : "Attendee updated",
"AlertType" : "Attendee",
"UserId" : ObjectId("5aead4a81a7ecc7230fb249c"),
"_id" : ObjectId("5af953ab67f3be54d4256f35")
},
],
"Comments" : [ ],
"Slides" : [
{
"Seq" : 1,
"Details" : "<p>Project Meeting</p>\n",
"_id" : ObjectId("5af7bcdff107cb7a105243f6"),
"Comments" : [
{
"_id" : ObjectId("5b45b854d217f62010fea8e7"),
"DateTime" : ISODate("2018-07-11T07:53:40.967Z"),
"IsFromOnline" : "3047",
"UserId" : ObjectId("5aead4431a7ecc7230fb249a"),
"Comment" : "test 123"
},
{
"_id" : ObjectId("5b45b89e7c32803a282e44db"),
"IsFromOnline" : "3043",
"DateTime" : ISODate("2018-07-11T07:58:22.648Z"),
"UserId" : ObjectId("5aead4431a7ecc7230fb249a"),
"Comment" : "new comments"
}
]
},
{
"Details" : "<p>second side</p>\n",
"Seq" : 2,
"_id" : ObjectId("5af7c843f107cb7a105243f7"),
"Comments" : [
{
"_id" : ObjectId("5b45b9bc569a4b284074fd08"),
"IsFromOnline" : "92179",
"DateTime" : ISODate("2018-07-11T08:03:01.851Z"),
"UserId" : ObjectId("5aead4431a7ecc7230fb249a"),
"Comment" : "test comments 123434343434343"
}
]
}
],
"Attendees" : [
ObjectId("5aead4a81a7ecc7230fb249c")
],
"Chairperson" : [
ObjectId("5aead4701a7ecc7230fb249b")
],
"__v" : 0,
"AcceptOrReject" : [
{
"Reason" : "More changes neened",
"Status" : "APPROVED",
"UserId" : ObjectId("5aead4701a7ecc7230fb249b"),
"CreatedDate" : ISODate("2018-05-14T09:15:23.385Z"),
"Comment" : "Will disucuss in next meeting"
}
]
}
For e.g i want to update Session "_id" : ObjectId("5af7bcdff107cb7a105243f5")
having Slides with Seq :1 and Comment from 'new comments' to 'Updated comments' with "IsFromOnline" : "3043".
i tried below and some other stuff, but it doesn't seem to work.
Session.update({
$and: [{
"_id": req.body.SessionId,"Slides.Seq": req.body.SeqNo
},
{
'Slides.Comments': {
$elemMatch: {
IsFromOnline: req.body.IsFromOnline
}
}
}
]
}, {
$set: {
'Slides.Comments.$.Comment': 'Updated comments'
}
})

Related

Populated nested schema in Mongoose

This is my Schema, I have a CampaignStat Object which has a nested Product Schema, but at the same time Product is another model.
const ProductsSchema = new Schema({
_id: {
type: mongoose.Schema.ObjectId,
ref: 'Product'
},
clickedAt: Date,
deviceInfo: {
type: Schema.Types.Mixed
}}, { _id: false })
const CampaignStatSchema = new Schema({
campaign: {
type: mongoose.Schema.ObjectId,
ref: 'Campaign'
},
subscriber: {
type: mongoose.Schema.ObjectId,
ref: 'Subscriber'
},
openedAt: Date,
products: [ProductsSchema]
}, {
timestamps: { createdAt: true, updatedAt: false }
})
An this is how is being stored in MongoDB
"_id" : ObjectId("5f18d01ecab4eb6175cc0f83"),
"subscriber" : ObjectId("5ed6890da2c99843280a0058"),
"campaign" : ObjectId("5ed937829ff2a1f99de55150"),
"products" : [
{
"_id" : ObjectId("5f160ca2014be4e159f32fcd")
},
{
"_id" : ObjectId("5f160ca2014be4e159f3302e")
},
{
"_id" : ObjectId("5f160ca2014be4e159f33036")
},
{
"_id" : ObjectId("5f160ca2014be4e159f3311a")
},
{
"_id" : ObjectId("5f160ca2014be4e159f33159")
}
],
"createdAt" : ISODate("2020-07-22T23:47:42.228Z"),
"__v" : 0
I need to populate Products, I'm doing this but I cannot get the Product collection attributes
const CampaignStats = await this.find({ campaign: "5ed937829ff2a1f99de55150" })
.populate('subscriber')
.populate({
path: 'products',
model: 'Product'
})
In case somebody gets into the same problem, I changed this (_id for product):
const ProductsSchema = new Schema({
product: {
type: mongoose.Schema.ObjectId,
ref: 'Product'
},
clickedAt: Date,
deviceInfo: {
type: Schema.Types.Mixed
}}, { _id: false })
And my query is like this:
this.find(query)
.populate({
path: 'products',
populate: {
path: 'product',
model: 'Product'
}
})

How to use populate in node js

I have to populate students in my data,
"attendances" : [
{
"_id" : ObjectId("5851702b9accfc6e70d55107"),
"students" : [
{
"student" : ObjectId("5850e6d596d4de3c1f4a0614"),
"_id" : ObjectId("5851702b9accfc6e70d55109"),
"ispresent" : "No"
}, }]
My schema,
attendances: [{
date: {
type: String,
default: ''
},
created_by: {
type: Schema.ObjectId,
ref: 'Employee'
},
students: [{
student: {
type: Schema.ObjectId,
ref: 'Student'
},
ispresent: {
type: String,
default: ''
}
}]
}],
Attendance.findById(id).populate('attendances.students')
I tried the above way but fails.Can any one please suggest help.Thanks.
You can write your population predicate by the dot notation while you're digging deeper into both object or array to refer at the end to another valid schema of type Schema.Types.ObjectId, so according to your mentioned schema, you query would be as follow:
Attendance.findById(id).populate('attendances.students.student')

mongoose: update field, push object in array [duplicate]

This question already has answers here:
Stop Mongoose from creating _id property for sub-document array items
(7 answers)
Closed 7 years ago.
I would like to add an element in an array in a mongo database:
db.keypairs.update( {pubkey: "1234567890"}, { $push: {listTxId: {txHash: "yyy", spent: false} } } )
The result is perfect:
listTxId" : [ { "txHash" : "xxx", "spent" : true },{ "txHash" : "yyy", "spent" : false } ]
Now I would like to do the same with node.js and mongoose
var res = wait.forMethod(Keypair,'update', {pubkey: "1234567890"}, { $push: { "listTxId": {"txHash":"zzz", "spent":false} } } );
Keypair is my node.js model for the mongoose collection:
var Keypair = require('./app/models/Keypair');
and wait.forMethod comes from a node module:
var wait = require('wait.for');
In the result, I have this "_id" element :
{ "txHash" : "zzz", "spent" : false, "_id" : ObjectId("56561571fea5d9a10a5771fd") }
QUESTION: where this ObjectId come from ? How can I get rid of it ?
UPDATE: mongoose schema:
var keypairSchema = mongoose.Schema({
userId : { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
pubkey : String,
privkeyWIF : String, // temp
balance : Number,
listTxId : [{
txHash : String,
spent : Boolean
}],
walletId : { type: mongoose.Schema.Types.ObjectId, ref: 'Wallet' },
description : { type: String, maxlength: 40 },
comments : String,
isMasterKey : { type: Boolean, default: false },
date : Date
});
Mongoose will put ids in your subdocument arrays. listTxId is a subdocument array. You can add _id: false to your schema to prevent this:
var keypairSchema = mongoose.Schema({
userId : { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
pubkey : String,
privkeyWIF : String, // temp
balance : Number,
listTxId : [{
_id: false,
txHash : String,
spent : Boolean
}],
walletId : { type: mongoose.Schema.Types.ObjectId, ref: 'Wallet' },
description : { type: String, maxlength: 40 },
comments : String,
isMasterKey : { type: Boolean, default: false },
date : Date
});

Why arrays of objects has ids on Mongoose?

I've went through some problems while saving some documents and realized that some inner documents has id references.
Let's take this schema for example:
var VisitSchema = mongoose.Schema({
user_id: { type: Schema.Types.ObjectId, ref: 'User' },
name: String,
city: {
name: String,
reference: String,
location: [Number]
},
photos: [{
image_url: String,
description: String
}]
});
When this schema is saved, here is the resulting document:
{
"_id" : ObjectId("5449eceeea5281056768aef8"),
"user_id" : ObjectId("540603dd797be100008b4340"),
"name" : "Test",
"photos" : [
{
"image_url" : "testURL",
"description" : "testDescription",
"_id" : ObjectId("5449eceeea5281056768aefb")
}
],
"city" : {
"name" : "New York, NY, United States",
"reference" : "CoQBdAAAAFfbZuaWptFtAkhGaO87UVSaXbyYwtTY_xX-pH84mS6QO2ypLr15znsCnYvaZ_N8CvwCBAr4y34PSQqyTUwxa5qbUKBK0yHnUFgTLKPQMFKqyQ8xd4vcDPNXf5XSxlpsXKKPYnU0AJZEVVxXLJ_6IBiUay9emFvNXPiYb7kT04NjEhB8fK-jKIZHJ5Bfz_mfyk2MGhTJwOPU68NQiV7RlAdb0Gca1bg0ew",
"location" : [
-74.0059413,
40.7127837
]
},
"__v" : 0
}
Why does the subdocument photos has an id reference? It doesn't make sense.
Thanks.

Cannot update a property in an embedded Array in mongoose

I'm working on a commenting system with mongoose/n,
users can comment, and like in reddit, users should vote each comment up or down.
and i have the following comment scheme:
var commentSchema = new Schema({
text: String,
level: { type: Number, min: 0, max: 30, default: 0},
slug: String,
full_slug: String,
discussion_id: { type: Schema.ObjectId, ref: 'Uranus' },
parent_id: {type: Schema.ObjectId,ref: 'Comment'},
score: [{
upvote: {type: Number,min: 0,max: 9000},
downvote: {type: Number,min: 0,max: 9000},
voter: {type: Schema.ObjectId,ref: 'Account'}
}],
updated: { type: Date, default: Date.now },
created: { type: Date, default: Date.now },
author: { type: Schema.ObjectId, ref: 'Account' },
});
it works just fine, but i have no clue, how to update the score-array. it just doesn't work.
Here is the sample json-data i got:
{
"__v" : 0,
"_id" : ObjectId("52a0d4ff779edff16d000006"),
"author" : ObjectId("529dfdda6b2d7a450c000009"),
"created" : ISODate("2013-12-05T19:33:19.229Z"),
"discussion_id" : ObjectId("529f7b04cbab31cc3e000004"),
"full_slug" : "2013.12.05.19.33.19:e1CDx79g8",
"level" : 0,
"score" : [
{
"upvote" : 1,
"downvote" : 0,
"voter" : ObjectId("529dfdda6b2d7a450c000009"),
"_id" : ObjectId("52a0d4ff779edff16d000007")
},
{
"upvote" : 0,
"downvote" : 1,
"voter" : ObjectId("52a0d9883027a89d6e000002"),
"_id" : ObjectId("52a0d9903027a89d6e000004")
},
{
"upvote" : 0,
"downvote" : 1,
"voter" : ObjectId("52a0d99a3027a89d6e000005"),
"_id" : ObjectId("52a0d9a63027a89d6e000007")
}
],
"slug" : "e1CDx79g8",
"text" : "A Comment",
"updated" : ISODate("2013-12-05T19:33:19.229Z")
}
so, i just update the comment by
var query = {
'score.voter': mongoose.Types.ObjectId(String('52a0d9883027a89d6e000002'))
};
Comment.update( query, {$set: {"score.$.upvote": 10}} )
The problem is, that it's just not updating.
i know, there are a few other questions regarding this problem, but all solutions are not working for me. i hope someone can help me.
UPDATE:
Found the problem, Seems like you have to have a callback on the update function like this:
Comment.update( query, {$set: {"score.$.upvote": 10}}, { multi: false }, function(err,n){
console.log("affected rows:", n)
});

Resources