Mongo pull object from array inside array - node.js

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" }}},
)

Related

Mongo update to many query

does anyone know how to change a propertie value in mongo
from
i changed JSON.units[0].services[0].label from etiket controle to AuditLabel
i tried this:
db.getCollection('assortiment').updateMany({"units.$[].services.$[].label": "etiket controle"},{ "$set": { "units.$[].services.$[].label": "AuditLabel" }})
but no succes because it dont select anything
{
"_id" : "764",
"meta" : {
"groupsId" : "764",
"type" : "DRYGR"
},
"units" : [
{
"unit" : "BASE_UNIT_OR_EACH",
"gtin" : "08711728556206",
"services" : [
{
"label" : "etiket controle",
"collection" : "gtins"
}
]
}
]
}
to
{
"_id" : "764",
"meta" : {
"groupsId" : "764",
"type" : "DRYGR"
},
"units" : [
{
"unit" : "BASE_UNIT_OR_EACH",
"gtin" : "08711728556206",
"services" : [
{
"label" : "AuditLabel",
"collection" : "gtins"
}
]
}
]
}
Try this code its work's for me
db.getCollection('assortiment').updateMany(
{
"units.services.label": "etiket controle"
},
{
"$set":
{ "units.$[].services.$[].label": "AuditLabel" }
}
)

update particular single subdocument in nested array in nodejs mongodb

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

Need to apply two group in sequence and second group should will have effect on result of first group

I want to group my data on the base of factoryId field and then each factory there will be multiple orders want to again group on basis of orderId as each order can contain multiple items. Here I am giving the example of my data and what I need and first group by which I tried.
{
"_id" : ObjectId("5b3e270c42d8004cea382e87"),
"factoryId" : ObjectId("5aa76190cef23a1561b8056c"),
"productId" : ObjectId("5aa78c66cef23a1561b80893"),
"orderId" : ObjectId("5b3e270c42d8004cea382e86"),
"generatedOrderId" : "3985-166770-4554",
"productName" : "Lakme Lotion"
},
{
"_id" : ObjectId("5b3e270c42d8004cea382e88"),
"factoryId" : ObjectId("5b39aed32832f72062e51c23"),
"productId" : ObjectId("5b3cb96139cec8341df52c4b"),
"orderId" : ObjectId("5b3e270c42d8004cea382e86"),
"generatedOrderId" : "3985-166770-4554",
"productName" : "Coke"
},
{
"_id" : ObjectId("5b3e27b07fe0d94d62b76b2a"),
"factoryId" : ObjectId("5aa76190cef23a1561b8057c"),
"productId" : ObjectId("5ac21075ac347a5fbf355028"),
"orderId" : ObjectId("5b3e27b07fe0d94d62b76b27"),
"generatedOrderId" : "3985-755507-7484",
"productName" : "Spoon"
}
And I want result as:
{
"factoryId":ObjectId("5aa76190cef23a1561b8057c"),
"orders":[
{
"orderId":ObjectId("5b3e270c42d8004cea382e86")
"items":[
{
"productName":"Lakme Lotion"
},
{
"productName":"Coke"
}
]
}
]
}
Can anyone help me with this?. Any help is appreciated.
I tried and It worked for me. Sorry
db.getCollection("transactions").aggregate(
[
{
"$group" : {
"_id" : "$orderId",
"items" : {
"$push" : "$$ROOT"
}
}
},
{
"$project" : {
"orderId" : "$_id",
"items" : "$items",
"_id" : 0
}
},
{
"$unwind" : {
"path" : "$items",
"preserveNullAndEmptyArrays" : false
}
},
{
"$group" : {
"_id" : "$items.factoryId",
"orders" : {
"$push" : "$$ROOT"
}
}
},
{
"$project" : {
"factoryId" : "$_id",
"orders" : "$orders",
"_id" : 0
}
}
]
);

Count where value does not match array

I have following offers collection
Here readBy contains the _id of the users...
Now I want to count the number of unRead offers for the userId = "5add82620d7f5b38240c63d4"
{
"_id" : ObjectId("5aeaab5ed6a9c97d0209260a"),
"expiresIn" : ISODate("2018-05-30T18:30:00.000Z"),
"name" : "Trip ",
"readBy" : [
ObjectId("5add82620d7f5b38240c63d4"),
ObjectId("5add82620d7f5b38240c63c6")
],
"__v" : 0
}
{
"_id" : ObjectId("5aeaab7dd6a9c97d0209260b"),
"expiresIn" : ISODate("2018-05-29T18:30:00.000Z"),
"name" : "Trip",
"readBy" : [ObjectId("5add82620d7f5b38240c63d4")],
"__v" : 0
}
{
"_id" : ObjectId("5aeae233d6a9c97d02092622"),
"expiresIn" : ISODate("2018-05-25T18:30:00.000Z"),
"name" : "two way off",
"readBy" : [],
}
{
"_id" : ObjectId("5aeae49643f10d284726069c"),
"expiresIn" : ISODate("2018-05-25T18:30:00.000Z"),
"name" : "two way off",
"readBy" : [],
}
{
"_id" : ObjectId("5aeae49743f10d284726069d"),
"expiresIn" : ISODate("2018-05-25T18:30:00.000Z"),
"name" : "two way off",
"readBy" : []
}
{
"_id" : ObjectId("5aeae49743f10d284726069e"),
"expiresIn" : ISODate("2018-05-25T18:30:00.000Z"),
"name" : "two way off",
"readBy" : []
}
so for the above collection my output should be
[{
numberOfUnreadOffers: 4
}]
because four of the collection does not have 5add82620d7f5b38240c63d4 in readBy array
You basically use $setIsSubset and $cond here:
var userId= "5add82620d7f5b38240c63d4";
Model.aggregate([
{ "$group": {
"_id": null,
"numberOfUnreadOffers": {
"$sum": {
"$cond": {
"if": {
"$setIsSubset": [[mongoose.Types.ObjectId(userId)], "$readBy"]
},
"then": 0,
"else": 1
}
}
}
}}
])
Of course you also need to "cast" using mongoose.Types.ObjectId from the "string" to a valid ObjectId value.
But really you get better performance from a simple count() instead:
Model.count({ "readBy": { "$ne": userId } })
So you really should not use .aggregate() for this at all.

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