update particular single subdocument in nested array in nodejs mongodb - node.js

I am new to nodejs and mongo db. I have nested subdocument type schema in mongo. Document type is Process => Subprocess => tasks => configs. These are in the format of nested arrays and can be multiple.
{
"_id" : ObjectId("5bcec0ee711fe511f4848c1d"),
"process_title" : "customer acquisition",
"subprocess" : [
{
"_id" : ObjectId("5bcec0f8711fe511f4848c1e"),
"subprocess_title" : "application",
"tasks" : [
{
"_id" : ObjectId("5bcec158711fe511f4848c1f"),
"task_title" : "pre screening",
"task_slug" : "pre-screening",
"task_configs" : [
{
"_id" : ObjectId("5bcec4b912582b01b84fe47a"),
"next_task" : "thanks"
}
]
},
{
"_id" : ObjectId("5bcec190711fe511f4848c20"),
"task_title" : "thanks",
"task_slug" : "thanks",
"task_configs" : [
{
"_id" : ObjectId("5bcec469ab23ab1fc0bbb9ed"),
"form_field" : "responseMessage",
"expression" : "=",
"expression_value" : "Approved4",
"success_task" : "signup",
"success_sub_process_id" : "5bcec0f8711fe511f4848c1e",
"fail_task" : "thanks",
"fail_sub_process_id" : "5bcec0f8711fe511f4848c1e"
}
]
},
{
"_id" : ObjectId("5bcec1c3711fe511f4848c21"),
"task_title" : "signup",
"task_slug" : "signup",
"task_configs" : [
{
"_id" : ObjectId("5bcec469ab23ab1fc0bbb9ed"),
"form_field" : "responseMessage",
"expression" : "=",
"expression_value" : "Approved4",
"success_task" : "signup",
"success_sub_process_id" : "5bcec0f8711fe511f4848c1e",
"fail_task" : "thanks",
"fail_sub_process_id" : "5bcec0f8711fe511f4848c1e"
}
]
}
]
}
],
"created_at" : ISODate("2018-10-23T06:34:22.676Z"),
"updated" : ISODate("2018-10-23T06:34:22.676Z"),
"__v" : 0
}
Now I want to update task_configs for a particular task. I am updating task_config on the basis of task_slug.

I found a way myself to update above query.
Workflow.updateOne({ "_id": new ObjectId(req.body.process_id), "subprocess._id": new ObjectId(req.body.sub_process_id), "subprocess.tasks.task_slug": req.body.task_slug },
{
$set: {
'subprocess.$.tasks.$[j].task_configs': req.body.task_configs
}
},
{
arrayFilters: [
{
"j.task_configs": req.body.task_configs
}]
})
.then(function (resp) {
console.log(resp)
res.json({ status: 'success', resp });
}).catch(function (err) {
res.status(500).json(err);
})

Related

Query an array of nested documents

I got this document:
{
"_id" : "111",
"email" : "michael#gmail.com",
"username" : "michael098",
"groups" : [
{
"_id" : "222"
"groupName" : "family",
"groupMembers" : [
{
"_id" : "333"
"name" : "Liam"
},
{
"_id" : "444"
"name" : "Noah"
}
]
},
{
"_id" : "555"
"groupName" : "friends",
"groupMembers" : [
{
"_id" : "666"
"name" : "Oliver"
}
]
}
]
}
I am trying to delete 1 group member by _id, for example if I get userId="111", groupId="222" and groupMemberId="444" the group member with _id="444" will delete.
Example of the document after this delete request:
{
"_id" : "111",
"email" : "michael#gmail.com",
"username" : "michael098",
"groups" : [
{
"_id" : "222"
"groupName" : "family",
"groupMembers" : [
{
"_id" : "333"
"name" : "Liam"
}
]
},
{
"_id" : "555"
"groupName" : "friends",
"groupMembers" : [
{
"_id" : "666"
"name" : "Oliver"
}
]
}
]
}
My attempt (with express and mongoose):
router.delete(
"/:userId/:groupId/:groupMemberId",
catchAsync(async (req, res) => {
const { userId, groupId, groupMemberId } = req.params;
const updatedUser = await User.findByIdAndUpdate(
userId,
{ $pull: { "groups.$.groupMembers": { _id: groupMemberId } } },
{ new: true }
);
res.send({ updatedUser });
})
);
The response from this request: I get an error: “The positional operator did not find the match needed from the query.”

Mongo pull object from array inside array

i have inside my mongoDB collection this document
{
"_id" : ObjectId("5b633025579fac22e74bf3be"),
"FLAGS" : [
{
"toSent" : [
{
"_id" : ObjectId("5b633025579fac22e74bf3c2"),
"phone" : "+84404040404"
},
{
"_id" : ObjectId("5b633025579fac22e74bf3c1"),
"phone" : "+212652253403"
},
{
"_id" : ObjectId("5b633025579fac22e74bf3c0"),
"phone" : "+212123456788"
}
],
"_id" : ObjectId("5b633025579fac22e74bf3bf"),
"action" : "group_p_a"
},
{
"toSent" : [
{
"_id" : ObjectId("5b633031579fac22e74bf3c9"),
"phone" : "+212651077199"
},
{
"_id" : ObjectId("5b633031579fac22e74bf3c8"),
"phone" : "+84404040404"
},
{
"_id" : ObjectId("5b633031579fac22e74bf3c7"),
"phone" : "+212652253403"
},
{
"_id" : ObjectId("5b633031579fac22e74bf3c6"),
"phone" : "+212123456788"
}
],
"_id" : ObjectId("5b633031579fac22e74bf3c5"),
"action" : "group_p_a"
}
],
"time" : ISODate("2018-08-02T16:24:05.747+0000"),
"action_user_phone" : "+212123456788",
"idGroup" : "e534379a-1580-4568-b5ec-6eaf981538d2",
"nomGroup" : "MOH FOR EVER",
"__v" : NumberInt(0)
}
TODO
I need to remove for example this element { "_id" : ObjectId("5b633025579fac22e74bf3c2"), "phone" : "+84404040404"}
WHAT I DID
GroupEvents.update({}, {$pull:{FLAGS:{$elemMatch:{toSent:{phone: "+84404040404"} }}}},function(err,ret){
if(err)
console.log("error"+err);
if(ret)
console.log(ret);
});
It remove all what's inside toSent event if it doesn't match.
Any help please
You need to use $ positional operator instead of $elemMatch here
GroupEvents.update(
{ "Flags.toSent.phone": "+84404040404" },
{ "$pull": { "FLAGS.$.toSent": { "phone": "+84404040404" }}},
)
If you want remove from every element of FLAGS array this you need to use $[] the all positional operator
GroupEvents.update(
{ "Flags.toSent.phone": "+84404040404" },
{ "$pull": { "FLAGS.$[].toSent": { "phone": "+84404040404" }}},
)

Targeting a query in Mongo to find and email nested in an object

I'm trying to do a query for an endpoint in my Node/Express & Mongo/Mongoose API.
Here is a representation of the document/schema I'm trying to query:
{
"_id" : ObjectId("59474bc3478604a75e1980e2"),
"initial" : "D",
"last_name" : "Spitz",
"first_name" : "Chris",
"owner_id" : "59474b92478604a75e1980e1",
"contacts" : [
{
"last_name" : "Jones",
"first_name" : "Tom",
"_id" : ObjectId("5947fd928389ffb393fbc310"),
"addresses" : [ ],
"phones" : [ ],
"emails" : [
{
"email_type" : "home",
"email_address" : "runner#running.com",
"_id" : ObjectId("5947fd928389ffb393fbc311")
},
{
"email_type" : "home",
"email_address" : "jake#samsonite.com",
"_id" : ObjectId("5947ff9ed8fa7cb4c781acc9")
}
]
},
{
"last_name" : "Smith",
"first_name" : "Linda",
"_id" : ObjectId("5947ff9ed8fa7cb4c781acc8"),
"addresses" : [ ],
"phones" : [ ],
"emails" : [
{
"email_type" : "home",
"email_address" : "chris#chrisnakea.com",
"_id" : ObjectId("5947ff9ed8fa7cb4c781acc9")
}
]
}
]
}
I'm trying to check if an email exists in the "contacts.email" array of the document.
Here is the way I'm checking (based on the whey it the item is nested in the schema above):
Profile.find({'contacts.emails.email_address':req.body.invited_email}, function(err, profile){
if(err)
console.log('Error in looking for profile.');
if(profile.contacts.emails.email_address !== null){
console.log('Found contact: ' + profile.contacts.emails.email_address);
} else {
console.log('Contact does not exist');
}
})
But for some reason I'm getting a "TypeError: Cannot read property 'emails' of undefined" error in the console when testing.
What am I missing here?

Node : Mongoose Updating User Schema with arrays

Here is my User Schema
{
"user_collection":[
{
"_id":"xxx",
"name":"NAME",
"prescription":
{
"doctor_id":
[{
"_id":"xxx",
"medicine_id":"MEDICINE_ID",
}]
},
"meal":{
"meal_name":{
"start_time":"START_TIME",
"end_time":"END_TIME"
}
},
"created_at":"CREATED_AT",
"updted_at":"UPDATED_AT"
}
]
}
Note : _id given just for understanding
I need to insert document inside the prescription array. Here is the condition
If the new doctor_id is given, it should add in the prescription array like
{
"_id" : ObjectId("5813288eaa0f1231de477d92"),
"name" : "andrew",
"prescription" : [
{
"prescription" : [
{
"_id" : ObjectId("58143d484e26a229873b0528"),
"medicine_id" : "10011241343"
}
],
"_id" : ObjectId("58143d484e26a229873b0527"),
"doctor_id" : "5813221ace684e2b3f5f0a6d"
}
]
}
And if i given the doctor_id that already exists it should add like
{
"_id" : ObjectId("5813288eaa0f1231de477d92"),
"name" : "andrew",
"prescription" : [
{
"prescription" : [
{
"_id" : ObjectId("58143d484e26a229873b0528"),
"medicine_id" : "10011241343"
}
],
"prescription" : [
{
"_id" : ObjectId("58143d484e26a229873b0529"),
"medicine_id" : "10011241349"
}
],
"_id" : ObjectId("58143d484e26a229873b0527"),
"doctor_id" : "5813221ace684e2b3f5f0a6d"
}
]
}
What i have tried is
dbModel.user.update({
_id: req.body.user_id
}, {
$set: {
prescription: [ { "doctor_id" : req.body.doctor_id, "prescription" : [
{
"medicine_id" : req.body.medicine_id
}]} ],
}
}, {
upsert: true
}, function(err) {
if (err) {
res.status(202).json({
"success": "0",
"message": err
})
} else {
res.status(200).json({
"success": "1",
"message": "Prescription given successfully"
});
}
})
I don't know how to check whether the doctor_id already exists and if it does not exists it should add a new array, and if it exists it should add inside the existing arrays
Take a look in this answer.
But basically you can use the $ operator which identifies an element in an array.
You can see here some mongodb array operators.

How to fetch specific fields in Mongo DB only values without keys?

My data set is following:
{ "_id" : "EVNQUERY-k9Uoo74Q3WcdmU", "event_data" : "{\"data\":\"helo\"}", "event_name" : "onOemPushAlert", "timestamp_start" : 1452678481433, "timestamp_end" : 1452678481433, "sender" : "USR-ADMIN", "status" : "pending", "query" : { "user" : { "and" : [ { "email" : { "eq" : "" } } ] } }, "updated_on" : ISODate("2016-01-13T09:48:01.459Z"), "created_on" : ISODate("2016-01-13T09:48:01.459Z") }
{ "_id" : "EVNQUERY-yAKmrbzs2JeaUY", "event_data" : "{\"data\":\"ji\"}", "event_name" : "onOemPushAlert", "timestamp_start" : 1452681060159, "timestamp_end" : 1452681060159, "sender" : "USR-ADMIN", "status" : "pending", "query" : { "user" : { "###and###" : [ { "email" : { "eq" : "" } } ] } }, "updated_on" : ISODate("2016-01-13T10:31:00.223Z"), "created_on" : ISODate("2016-01-13T10:31:00.223Z") }
{ "_id" : "EVNQUERY-0NeCstt2eJchDZ", "event_data" : "{\"data\":\"hyg\"}", "event_name" : "onOemPushAlert", "timestamp_start" : 1452681073882, "timestamp_end" : 1452681073882, "sender" : "USR-ADMIN", "status" : "pending", "query" : { "user" : { "###and###" : [ { "email" : { "eq" : "" } } ] } }, "updated_on" : ISODate("2016-01-13T10:31:13.897Z"), "created_on" : ISODate("2016-01-13T10:31:13.897Z") }
and i am running following query
db.eventqueries.find({},{_id:1})
but it give me
{ "_id" : "EVNQUERY-k9Uoo74Q3WcdmU" }
{ "_id" : "EVNQUERY-yAKmrbzs2JeaUY" }
{ "_id" : "EVNQUERY-0NeCstt2eJchDZ" }
but what i want is
["EVNQUERY-k9Uoo74Q3WcdmU", "EVNQUERY-yAKmrbzs2JeaUY", "EVNQUERY-0NeCstt2eJchDZ"]
Perform a distinct() query against the _id field on the collection:
db.eventqueries.distinct("_id")
In the node.js driver run the distinct() command which would have a callback with the results:
collection.distinct("_id", function(err, docs) {
if (err) { /* handle error */ };
console.log(docs);
});
You can use aggregation to achieve what you want. You can try this out
db.eventqueries.aggregate([
{
$group : {
keys : { $push : "_id" }
}
}
])

Resources