How to remove an Array of ObjectID's in mongodb? - node.js

I have two collections, campgrounds and reviews while deleting an review it stays in object array in campgrounds as an ObjectID ref and i can't find a way to delete them from there.
I tried
db.campgrounds.update({ title: "Ancient Hunting Camp" }, { $pull:{id:"60f8293044b0cc40c409f2f7"}})
db.campgrounds.update({ title: "Ancient Hunting Camp" }, { $pull: {reviews:{id:"60f8293044b0cc40c409f2f7"}}})
db.campgrounds.update({ title: "Ancient Hunting Camp" }, { $pullAll: {reviews:[]}},{multi:true})
db.campgrounds.update({ title: "Ancient Hunting Camp" }, { $pull: { reviews: {}}}, {multi:true})
db.campgrounds.update({ _id: "603d7a10f969af31484fb56e" }, { $pull: { reviews: "ratings"}})
db.campgrounds.update({ _id: "603d7a10f969af31484fb56e" }, { $pull: { reviews: ObjectId("60f976cd6132a91a20bd6679") }}
I've had these results
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
or
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
or
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 2,
"errmsg" : "Cannot apply $pull to a non-array value"
}
})`
Campground Schema
const CampgroundSchema = new Schema({
title: String,
image: String,
price: Number,
description: String,
location: String,
tel: Number,
website: String,
email: String,
reviews: [
{
type: Schema.Types.ObjectId,
ref: 'Review'
}
]
})

Related

Update Sub Sub Array item in MongoDB

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'
}
})

Mongoose: updating a single sub-document issues

Schema:
var educationSchema = new Schema({
schoolName: String,
startDate: Number,
endDate: Number,
degree: String,
major: String,
grade: String
});
var UserSchema = new Schema({
firstName: String,
lastName: String,
education: [educationSchema]
});
Update code:
User.findOneAndUpdate(
{"_id": req.user.id, "education._id": req.body.id},
{
"$set": {
"education.$": req.body
}
},
function(err, edu) {
}
);
Now, if the user only edits the schoolName on the UI the following happens:
Pre-save State:
{
"_id" : ObjectId("5878fb4f51ec530358fea907"),
"firstName" : "John",
"lastName" : "Doe",
"education" : [
{
"schoolName" : "ABC",
"startDate" : 1998,
"endDate" : 2005,
"degree" : "Bachelor’s Degree",
"major" : "CS",
"grade" : "3.5",
"_id" : ObjectId("5878fbb951ec530358fea909")
}
]
}
Post-save State:
"education" : [
{
"schoolName" : "XYZ"
}
]
Is $set not the right operator to use?
Updating education.$ updates the sub-document. If you want to update only the schoolName you must use education.$.schoolName.
Change your update code to:
User.findOneAndUpdate(
{"_id": req.user.id, "education._id": req.body.id},
{
"$set": {
"education.$.schoolName": req.body
}
},
function(err, edu) {
}
);
EDIT: (update any field sent through req.body)
const update = {};
Object.getOwnPropertyNames(req.body).forEach(key => {
update['education.$.' + key] = req.body[key];
});
User.findOneAndUpdate(
{"_id": req.user.id, "education._id": req.body.id},
{
"$set": update
},
function(err, edu) {
}
);

selective find in mongoose

USER SCHEMA:
{
friends: [{
user_id: {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User'},
name: {type: String, required :true},
age: {type: Number, required: true}
}],
privacy_settings : {
visibility : {type : Number, enum: [0,1,2]},
permission : {type : Number, enum : [0,1]},
}
}
Above is a sub section of user schema. I want to filter out the friends whose user id's don't exist. Right now what I get is:
QUERY RESULT:
friends:
[ {},
{},
{},
{},
{},
{ user_id: 570f733f0e3fbfb7690b2384 },
{},
{},
{ user_id: 570f52b30e3fbfb7690b09f4 },
{},
{},
{},
{ user_id: 570f57490e3fbfb7690b0afe },
{ user_id: 571072576952b11f0320f324 } ],
The problem is I don't want these {}, just the data where user_id exists.
QUERY USED
user.findOne(
{_id: some_mongoose_id},
{'friends.userid privacy_settings'}, function(err,result){
console.log(err,result);
}
)
How can I go about this ?
Try This:
user.find({"friends.user_id" : {$ne : null}},function(err,data){
if(data){
//console.log(data);
}
});

How to set limit for array size in Mongoose schema

Would you be kind to tell me is there any way to set limitation on array size while creating Mongoose schema. For example
var peopleSchema = new Schema({
name: {
type: String,
required: true,
default: true
},
/* here I want to have limit: no more than 10 friends.
Is it possible to define in schema?*/
friends: [{
type: Schema.Types.ObjectId,
ref: 'peopleModel'
}]
})
With a small tweak to your schema setup you can add a validate option:
var peopleSchema = new Schema({
name: {
type: String,
required: true,
default: true
},
friends: {
type: [{
type: Schema.Types.ObjectId,
ref: 'peopleModel'
}],
validate: [arrayLimit, '{PATH} exceeds the limit of 10']
}
});
function arrayLimit(val) {
return val.length <= 10;
}
starting from mongo 3.6 you can add validation for a collection at server end, each document inserted/updated will be validated against the validator $jsonSchema, only the valid gets inserted, validation error will be for invalid documents
db.createCollection("people", {
validator: {
$jsonSchema: {
bsonType: "object",
required: [ "name" ],
properties: {
name: {
bsonType: ["string"],
description: "must be a string"
},
friends: {
bsonType: ["array"],
items : { bsonType: ["string"] },
minItems: 0,
maxItems: 10,
description: "must be a array of string and max is 10"
}
}
}
}
});
collection
> db.people.find()
valid document
> db.people.insert({name: 'abc' , friends : ['1','2','3','4','5','6','7','8','9','10']})
WriteResult({ "nInserted" : 1 })
invalid document
> db.people.insert({name: 'def' , friends : ['1','2','3','4','5','6','7','8','9','10', '11']})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
find
> db.people.find()
{ "_id" : ObjectId("5a9779b60546616d5377ec1c"), "name" : "abc", "friends" : [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" ] }
>
You can use $slice modifier at the time you push new friend id into your array
https://docs.mongodb.com/manual/reference/operator/update/slice/#up._S_slice
$push: {
friends: {
$each: [id],
$slice: -10
}
}
This is my schema and array limit on assignedToId via an external function.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const taskSchema = new Schema({
parentTask: {
trim: true,
type: Schema.Types.ObjectId,
ref: "task",
},
assignedToId: [{
trim: true,
type: Schema.Types.ObjectId,
ref: "Employees",
}],
createdBy: {
trim: true,
type: Schema.Types.ObjectId,
ref: "Employees",
required: [true, "User ID is required"]
},
createdByName: {
trim: true,
type: String,
required: [true, "Creater name is required"]
},
},
{
timestamps: true
});
// Validations for assignedTo employees' size
taskSchema.path('assignedToId').validate(function (value) {
console.log(value.length)
if (value.length > 10) {
throw new Error("Assigned person's size can't be greater than 10!");
}
});
const Tasks = mongoose.model("Tasks", taskSchema);
module.exports = Tasks;

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