Mongo db update to array object - javascript

I have array object inside my collection. i'm getting extra square bracket when i try to update data into the array object.
here is the code.
var comments = [{
'COMMENTED_BY' : employee.SYSTEM_USER_ID,
'COMMENT' : employee.FIRST_NAME+" "+employee.LAST_NAME+" Started working on this comlaint"
}];
if(req.body.complaint.comment){
comments.push({'COMMENTED_BY' : employee.SYSTEM_USER_ID,'COMMENT': req.body.complaint.comment});
}
Complaint.findByIdAndUpdate(
req.body.complaint.complaintId,
{$set: {'STATUS': 1}, $push: {"COMMENTS": comments}},
{safe: true, upsert: true},
function(err, model) {
My collection looks like below
{
"COMMENT" : "media delete confirmation UI issue",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fe9e1a5ee92201b58011e"),
"CREATED_AT" : ISODate("2016-06-14T11:26:25.003Z")
},
{
"COMMENT" : "Could someone explain to me how Luke Ronchi gets in when Tom Latham is a very capable keeper as well as batsman? Why not another specialist batsman/bowler?",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fea19a5ee92201b58011f"),
"CREATED_AT" : ISODate("2016-06-14T11:27:21.136Z")
},
[
{
"COMMENT" : "media delete confirmation UI issue",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fe9e1a5ee92201b58011e"),
"CREATED_AT" : ISODate("2016-06-14T11:26:25.003Z")
},
{
"COMMENT" : "Could someone explain to me how Luke Ronchi gets in when Tom Latham is a very capable keeper as well as batsman? Why not another specialist batsman/bowler?",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fea19a5ee92201b58011f"),
"CREATED_AT" : ISODate("2016-06-14T11:27:21.136Z")
}
]
i want to remove the extra [] brackets

This is happening because, you are just pushing array of objects, comment, into COMMENTS array field while updating. Use $each instead, while pushing array of objects.
See doc-$each for more info.
Try the following query. :-
Complaint.findByIdAndUpdate(
req.body.complaint.complaintId,
{$set: {'STATUS': 1}, $push: {"COMMENTS":{$each : comments}},
{safe: true, upsert: true})
Hope this will solve your issue.

Related

only edit (update) fields provided by form into mongoose subdocument

i wanted to update my mongoose subdocument with whatever field i fill in the form its working fine but the problem i am facing is if any of the field is left empty and then i submit i want it to just update the subdocumnet with just the fields provided by the form and fields which are not provided should be left with what it was before. currently it is deleting the fields not provided by form inside subdocument after the update
this is the update fn i am currently using
List.updateOne(
{"questionSet._id": questId},
{
$set: {
"questionSet.$": req.body
}
},
{new: true, useFindAndModify: false},
(e)=>{
if(e){
console.log(e);
res.redirect("/admin-edit-quest")
} else {
res.redirect("/admin-edit-quest")
}
}
)
this is eg. of my mongoose model
list: { "_id" : ObjectId("60f2cc07275bbb30d8cb268e"),
"listName" : "dsa",
"aboutList" : "dsa queestions",
questionSet" : [ { "solved" : false,
"_id" : ObjectId("60f2cc12275bbb30d8cb2695"),
"topic" : "array",
"name" : "array is best",
"url" : "www.arr.com",
"listname" : "dsa",
"__v" : 0 },
{ "solved" : false,
"_id" : ObjectId("60f2cc1b275bbb30d8cb269d"),
"topic" : "linked list",
"name" : "reverse list",
"url" : "www.list.com",
"listname" : "dsa",
"__v" : 0 }
],
"__v" : 2
}
Need to delete keys with blank values from req.body:
pruned_body = {}
body = JSON.parse(reg.body)
Object.keys(body).forEach(function (key) {
if (body[key]) {
pruned_body[key] = body[key]
}})
And then use pruned_body in $set.

MongoDB query using $and and $or

I trying to perform a query using $and and $or in MongoDB. Sadly I've had no luck. I found several similar questions posted here on Stack Overflow, this one came closest.
mongodb queries both with AND and OR
Unfortunately the solution did not work for me. I want to allow user to search by project id or title. I do have code that check if the q variable past in is a valid ObjectId before I include it.
Here is my query:
Project.find({
$and : [
{ $or : [ { title: {$regex : req.body.q} }, { _id: req.body.q } ] },
{ userID: req.session.userID }
]
}).then(project => {
console.log(project);
});
sample document:
{ "_id" : ObjectId("5afb583e8341f161a0c950af"), "title" : "Learn Node.js", "status" : "In Progress", "createdOn" : "2014-06-05 22:39:00.000Z" }
{ "_id" : ObjectId("4fe8736dc27bc8be56947d61"), "title" : "Learn MongoDB", "status" : "In Progress", "createdOn" : "2014-06-05 22:39:00.000Z" }
What am I missing?

What is causing "The dollar ($) prefixed field '$conditionalHandlers' in 'collaborators..$conditionalHandlers' is not valid for storage."

I am writing a Node/Express/Mongoose (latest versions) application which has "Projects" with a list of "collaborators" which are IDS of "Users". Until now, I've been storing the list of foreign keys as hex strings. This is now making it difficult to perform some slightly more complex aggregation, so I have decided to store them as ObjectId type instead, which makes the joins simpler.
In the function which creates the array, the push(userId) version works fine, adding collaborators to the array. However pushing an ObjectId into the array, or assigning an array containing an ObjectId fails with
"The dollar ($) prefixed field '$conditionalHandlers' in
'collaborators..$conditionalHandlers' is not valid for storage."
function addCollaborator(projectId, userId, fn){
projectModel.findById(projectId, (err, project)=>{
if(err) return fn(err);
project.collaborators.push( new Schema.Types.ObjectId(userId)); // errors
// project.collaborators = [ new Schema.Types.ObjectId(userId) ]; // errors
// project.collaborators.push( userId); // works
project.save((err)=>{
logService.error('Error adding collaborator to project: '+err.toString());
});
fn(null);
});
}
Project model:
const ProjectSchema = new mongoose.Schema({
name: String,
create_date: Date,
administrators: Array, // list of user._id
collaborators: Array, // list of user._id ObjectIds
});
With the text IDs, I get projects looking like:
{ "_id" : ObjectId("594e2222a26ca3505c18c674"),
"name" : "Pips 2nd Project", "create_date" : ISODate("2017-06-24T08:26:10.498Z"),
"collaborators" : [ "5936a3576d6c5a3ef4ee0936" ],
"administrators" : [ "594dbba8186f1a2f5ad7539c" ], "__v" : 1 }
When it breaks, I log the error, and am left with an empty array:
{ "_id" : ObjectId("594e278b6a68a2815b043bd1"),
"name" : "Pips third Project", "create_date" : ISODate("2017-06-24T08:49:15.091Z"),
"collaborators" : [ ],
"administrators" : [ "594dbba8186f1a2f5ad7539c" ], "__v" : 0 }
What I want to achieve is:
{ "_id" : ObjectId("594e2222a26ca3505c18c674"),
"name" : "Pips 2nd Project", "create_date" : ISODate("2017-06-24T08:26:10.498Z"),
"collaborators" : [ Object("5936a3576d6c5a3ef4ee0936") ],
"administrators" : [ "594dbba8186f1a2f5ad7539c" ], "__v" : 1 }
I've seen a few other SO's or github issues, but none seem to explain the problem. This one has the same problem, but "solved" it by using strings - which is the opposite of my issue.
After reading some other posts (e.g.), I realised I was using the wrong method to create an ObjectId from a hex string.
new Schema.Types.ObjectId(userId) // not right!
Should be:
mongoose.Types.ObjectId(userId)
So this works as expected now:
project.collaborators.push( mongoose.Types.ObjectId(userId));
and produces:
{ "_id" : ObjectId("594e278b6a68a2815b043bd1"),
"name" : "Pips third Project", "create_date" : ISODate("2017-06-24T08:49:15.091Z"),
"collaborators" : [ ObjectId("5936a3576d6c5a3ef4ee0936") ],
"administrators" : [ "594dbba8186f1a2f5ad7539c" ], "__v" : 1 }

Add to Collection if not found

I have an embedded document in my collection name as likes:
{
"_id" : ObjectId("57a31e18fa0299542ab8dd80"),
"created" : ISODate("2016-08-04T10:51:04.971Z"),
"likes" : [
{
"user" : ObjectId("1"),
"date" : 123
},
{
"user" : ObjectId("2"),
"date" : 456
}
],
"comments" : [],
"tag" : []
}
A User can like only one time. So there must be only one entry per User.
The problem is: It looks for date too in the object list, though I just want to search the user and add current date if entry not found. Because date differs every time and I get duplicated entries for same user.
Here is my mongoose query:
var likeObj = {
"user": "1", //user id
"date": Utils.getUnixTimeStamp() //date
};
post.update({_id: postId}, {$addToSet: {"likes": likeObj}} ,function(err,doc){
//success
});
You can add the user to the query:
post.update({_id: postId,
likes: {$not: {$elemMatch: {user: likeObj.user}}}},
{$addToSet: {"likes": likeObj}} ,function(err,doc){
});

updating mongodb using $push operator in angular-meteor

I am trying to push arrays from one collection to another.
this is the code I used in my server js
updateSettings: function(generalValue) {
let userId = Meteor.userId();
let settingsDetails = GeneralSettings.findOne({
"_id": generalValue
});
Meteor.users.update({
_id: userId
}, {
$push: {
"settings._id": generalValue,
"settings.name": settingsDetails.name,
"settings.description": settingsDetails.description,
"settings.tag": settingsDetails.tag,
"settings.type": settingsDetails.type,
"settings.status": settingsDetails.status
}
})
}
updateSettings is the meteor method. GeneralSettings is the first collection and user is the second collection. I want to push arrays from GeneralSettings to users collection. While I try this the result i got is like
"settings" : {
"_id" : [
"GdfaHPoT5FXW78aw5",
"GdfaHPoT5FXW78awi"
],
"name" : [
"URL",
"TEXT"
],
"description" : [
"https://docs.mongodb.org/manual/reference/method/db.collection.update/",
"this is a random text"
],
"tag" : [
"This is a demo of an Url selected",
"demo for random text"
],
"type" : [
"url",
"text"
],
"status" : [
false,
false
]
}
But the output I want is
"settings" : {
"_id" : "GdfaHPoT5FXW78aw5",
"name" : "URL",
"description" :
"https://docs.mongodb.org/manual/reference/method/db.collection.update/",
"tag" :"This is a demo of an Url selected",
"type" : "url",
"status" : false
},
What changes to be made in my server.js inorder to get this output
This is one case where you "do not want" to use "dot notation". The $push operator expects and Object or is basically going to add the "right side" to the array named in the "left side key":
// Make your life easy and just update this object
settingDetails._id = generalValue;
// Then you are just "pushing" the whole thing into the "settings" array
Meteor.users.update(
{ _id: userId },
{ "$push": { "settings": settingDetails } }
)
When you used "dot notation" on each item, then that is asking to create "arrays" for "each" of the individual "keys" provided. So it's just "one" array key, and the object to add as the argument.

Categories