How can I specific array values as out as given below? - arrays

I was get an result of aggregate query from collection using $facet and $group aggregate but our development team does not satisfies with this result they are asked result must not be an objects given end
{
"_id" : ObjectId("6316e1b9a9ac1f9acceaf488"),
"status_counts" : [
{
"_id" : {
"status" : "Closed"
},
"count" : 59662.0
},
{
"_id" : {
"status" : "Open"
},
"count" : 695.0
},
{
"_id" : {
"status" : "Pending"
},
"count" : 4039.0
}
],
"Priority_counts" : [
{
"_id" : {
"Priority" : "Escalated"
},
"count" : 4722.0
},
{
"_id" : {
"Priority" : "Low"
},
"count" : 11.0
},
{
"_id" : {
"Priority" : "High"
},
"count" : 1.0
},
{
"_id" : {
"Priority" : "Medium"
},
"count" : 1.0
}
],
"assigned" : [
{
"_id" : true,
"count" : 4351.0
},
{
"_id" : false,
"count" : 383.0
}
],
"transfered" : [
{
"_id" : true,
"count" : 245.0
}
],
"cc" : [
{
"_id" : true,
"count" : 4.0
}
]
}
===================================================================================
From the above document expected output as below.. can anyone suggest me please..
{
"_id" : ObjectId("6316e1b9a9ac1f9acceaf488"),
"status_counts" : [
{
"status" : "Closed",
"count" : 59662.0
},
{
"status" : "Open"
"count" : 695.0
},
{
"status" : "Pending"
"count" : 4039.0
}
],
"Priority_counts" : [
{
"Priority" : "Escalated"
"count" : 4722.0
},
{
"Priority" : "Low"
"count" : 11.0
},
{
"Priority" : "High"
"count" : 1.0
},
{
"Priority" : "Medium"
"count" : 1.0
}
],
"assigned" : [
{
"_id" : true,
"count" : 4351.0
},
{
"_id" : false,
"count" : 383.0
}
],
"transfered" : [
{
"_id" : true,
"count" : 245.0
}
],
"cc" : [
{
"_id" : true,
"count" : 4.0
}
]
}

Related

not able to query through an array in mongodb aggregation

this is the collection "Record" :
{
"_id" : "883f6174-fbbb-47f8-b280-7a798e8c0664",
"history" : [
{
"_id" : "6bdd2919-9fe5-48b8-a009-5dec0efc10c3",
"oldStatus" : "-NA-",
"newStatus" : "IN_PROGRESS",
"createdAt" : ISODate("2022-07-22T20:58:30.361Z")
},
{
"_id" : "eedb3775-93e2-4f0d-afda-0032b7b343dd",
"oldStatus" : "IN_PROGRESS",
"newStatus" : "ACCEPTED",
"createdAt" : ISODate("2022-10-10T16:30:04.781Z")
}
],
"source" : {
"$ref" : "Source",
"$id" : "65268f59-2a92-4414-8a79-c454c8059005"
},
"pipelineCreatedAt" : ISODate("2022-07-22T20:58:30.361Z")
}
I tried
{$addFields: {inProgressDate : {$cond:{if:{$and: [{ $eq: [ "$history.oldStatus", '-NA-' ] },{ $eq: [ "$history.newStatus", 'IN_PROGRESS' ] }]},then:"$history.createdAt",else:null}}}}
Expecting
My goal is :
WHERE progress time = oldStatus : "-NA-" and newStatus : "IN_PROGRESS"
and accepted time = oldStatus : "IN_PROGRESS" and newStatus : "ACCEPTED"

Push to array based on other attributes

Object structure (example only, there are thousands of callbacks in one object):
{
"_id" : ObjectId("5ce82dd1eed5a17f33ec025a"),
"id" : "AAA",
"pac" : "",
"callbacks" : [
{
"_id" : ObjectId("5ce82e29eed5a17f33ec0287"),
"timestamp" : 1558720040,
"type" : "data_bidir",
"seqNumber" : 49,
"messages" : [
{
"isCode" : true,
"_id" : ObjectId("5ce82e29eed5a17f33ec0294"),
"key" : "action",
"value" : "extra_long_press"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e29eed5a17f33ec0293"),
"key" : "version",
"value" : "6"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e29eed5a17f33ec0292"),
"key" : "firmware",
"value" : "0.45"
}
],
"created" : ISODate("2019-05-24T17:47:21.476Z")
},
{
"_id" : ObjectId("5ce82e42eed5a17f33ec0295"),
"timestamp" : 1558720040,
"type" : "service_geoloc",
"seqNumber" : 49,
"messages" : [
{
"isCode" : true,
"_id" : ObjectId("5ce82e42eed5a17f33ec029b"),
"key" : "lqi",
"value" : "Good"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e42eed5a17f33ec029a"),
"key" : "latitude",
"value" : "50.67593721530616"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e42eed5a17f33ec0299"),
"key" : "longitude",
"value" : "14.03118116624828"
},
{
"isCode" : false,
"_id" : ObjectId("5ce82e42eed5a17f33ec0298"),
"key" : "radius",
"value" : "8514"
},
{
"isCode" : true,
"_id" : ObjectId("5ce82e42eed5a17f33ec0297"),
"key" : "da_source",
"value" : "2"
},
{
"isCode" : true,
"_id" : ObjectId("5ce82e42eed5a17f33ec0296"),
"key" : "da_status",
"value" : "1"
}
],
"created" : ISODate("2019-05-24T17:47:46.547Z")
}
]
}
I need to push object to all messages only if a) callbacks.type is "service_geoloc" and b) if messages contains key = da_source and value = 2 (in sample data - the second callback would be affected).
The condition a) is easily managed by arrayFilters:
db.getCollection("devices").updateMany(
{ id: 'AAA'},
{ $push: {
"callbacks.$[c].messages" : {
$each: [{key: "action", value: "atlas_position_network", isCode: true}],
$position: 0
}
}
},
{ arrayFilters: [{"c.type": "service_geoloc"}], multi: true}
)
But I cannot figure out how to apply the condition b). I also tried elemMatch - it worked with both conditions but it updated only one message.
I was able to do it in 2 steps. Maybe it is impossible to do it in one step using shell.
Step 1 = push the item into messages array with general value:
db.getCollection("devices").updateMany(
{ id: 'AAA'},
{ $push: {
"callbacks.$[c].messages" : {
$each: [{key: "action", value: "atlas_position_network", isCode: true}],
$position: 0
}
}
},
{ arrayFilters: [{"c.type": "service_geoloc"}], multi: true}
)
Step 2 = Update the value based on other item on fixed position:
db.getCollection('devices').updateMany(
{ id: 'AAA' },
{ $set: { "callbacks.$[c].messages.0.value": "atlas_position_wifi"} },
{ arrayFilters: [{ "c.type": "service_geoloc", "c.messages.5.value": "6", "c.messages.5.key": "da_source" }], multi: true }
)

count inner array mongoose

I want to do a count on an array. This my model
modelDetail.aggregate([
{
$group: {
_id: '$main_section.dept',
count: {$sum: 'first_array.second_array.main_data'}
}
}
], function (err, result) {
if (err) {
//next(err);
console.log(err);
} else {
console.log(JSON.stringify(result));
res.json(result);
}
});
This is bringing out 0 for all the result. Output is below
[{"_id":"design","count":0},
{"_id":"training","count":0},
{"_id":"forecast","count":0},
{"_id":"internal audit","count":0},
{"_id":"research","count":0}]
I wanted to get the count of all the data
this is my schema
var userSchema = mongoose.Schema({
main_section :{
dept : String
},
first_array :[{//
floor : String,
second_array :[{//3rd level
name : String,//4th level
date : String
}]
}]
});
this is the data in the json
{ "_id" : "5bb39baf40f87f17f01734f8",
"main_section" : {
"dept" : "design"
},
"first_array" : [{ "_id" : "5bb39baf40f87f17f01734fc", "floor" : "2nd floor" ,
"second_array" : [
{ "_id" : "5bc102f6dff41a0e844dd2b7", "name" : "Blake Tyson", "date" : "2018-10-12T00:00:00Z" },
{ "_id" : "5bc102fddff41a0e844dd2bb", "name" : "Meagan Shawn", "date" : "2018-10-12T00:00:00Z" },
{ "_id" : "5bc1044dbba8b31ed42e7408", "name" : "Stephen Stone", "date" : "2018-10-12T00:00:00Z" }
]
}]
},
{ "_id" : "5bb39baf40f87f17f01734f8",
"main_section" : {
"dept" : "training"
},
"first_array" : [{ "_id" : "5bb39baf40f87f17f01734fc", "floor" : "1st floor",
"second_array" : [
{ "_id" : "5bc102f6dff41a0e844dd2b7", "name" : "Micheal Harrison", "date" : "2018-10-12T00:00:00Z" },
{ "_id" : "5bc102fddff41a0e844dd2bb", "name" : "Favour Reality", "date" : "2018-10-12T00:00:00Z" },
{ "_id" : "5bc1044dbba8b31ed42e7108", "name" : "Gift Myers", "date" : "2018-10-12T00:00:00Z" },
{ "_id" : "5bc1044dbba8b31ed42e71a1", "name" : "Drake Hills", "date" : "2018-10-12T00:00:00Z" },
{ "_id" : "5bc1044dbba8b31ed42e74c2", "name" : "Hashtan Priest", "date" : "2018-10-12T00:00:00Z" }
]
}]
},
{ "_id" : "5b98987f08925c0f5cd86780",
"main_section" : {
"dept" : "forecast"
},
"first_array" : [{ "_id" : "5b98987f08925c0f5cd86784", "floor" : "4th floor",
"second_array" : [ ]
}]
},
{ "_id" : "5b98187f08924c0f5ad86790",
"main_section" : {
"dept" : "internal audit"
},
"first_array" : [{ "_id" : "5b98987f08925c0f5cd86784", "floor" : "4th floor",
"second_array" : [ ]
}]
},
{ "_id" : "5b98187f08924c0f5ad86790",
"main_section" : {
"dept" : "research"
},
"first_array" : [{ "_id" : "5b98987f08925c0f5cd86784", "floor" : "4th floor",
"second_array" : [ ]
}]
}
Basically what i was hoping to do is to let each of the array produces the total number of elements
in the array for second alongside with the main section so for example
design would output 3
training would output 5
forecast would output 0
internal audit would output 0
research would output 0
So, any help is greatly appreciated!

mongo query - getting a specific object (its `_id` is known) from array of object BUT this array is also a part of list of documents

how can I query to get the specific message from either inbox or outbox given that I have its _id --> i.e. message id.
this is my route
get("/getSpecificMessage/{Message_id}", (req, res) => {..}
what I can do is find all the buyer/dealer and then go through inbox/outbox of all the buyer/dealer and then find the message with _id i.e. message_id
--> can I do it better then that.
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e1"),
"address" : {
"proper_address" : "sarai kale khan",
"lat" : 28.58894,
"long" : "77.25692"
},
"name" : "prashant",
"password" : "jfalksdjlk;jasdl",
"email" : "prashant#gmail.com",
"inbox" : [
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e4"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"from" : "1#1.com",
"message" : "message_1"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e3"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"from" : "2#2.com",
"message" : "message_2"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e2"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"from" : "3#3.com",
"message" : "message_3"
}
],
"outbox" : [
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e7"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"to" : "1#1.com",
"message" : "message_4"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e6"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"to" : "1#1.com",
"message" : "message_5"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e5"),
"date" : ISODate("2018-09-04T23:03:41.627Z"),
"to" : "1#1.com",
"message" : "message_6"
}
],
"__v" : 0
}
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e8"),
"address" : {
"proper_address" : "najafgarah",
"lat" : 28.58894,
"long" : "77.25692"
},
"name" : "rahul",
"password" : "jkalsjdflasdl",
"email" : "rahul#gmail.com",
"inbox" : [
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083eb"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"from" : "1#1.com",
"message" : "message_1"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ea"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"from" : "2#2.com",
"message" : "message_2"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083e9"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"from" : "3#3.com",
"message" : "message_3"
}
],
"outbox" : [
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ee"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"to" : "1#1.com",
"message" : "message_4"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ed"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"to" : "1#1.com",
"message" : "message_5"
},
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ec"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"to" : "1#1.com",
"message" : "message_6"
}
],
"__v" : 0
}
So if I have the _id = 5b8f0f4de276dd1e0ff083ea and I want
{
"_id" : ObjectId("5b8f0f4de276dd1e0ff083ea"),
"date" : ISODate("2018-09-04T23:03:41.639Z"),
"from" : "2#2.com",
"message" : "message_2"
}
I am not sure if you want it using MongoDB scripts or your app language (Nodejs if I am mistaken)
This is how it works on Mongo Shell Script
db.MODEL.find( { _id: DOCUMENT_ID },
{ inbox: { $elemMatch: { _id: MESSAGE_ID } } } )
Documentation is here
If this is not what you want, please update your post and add which language/framework you are using
This is what you could do using the aggregation framework:
var oId = new ObjectId("5b8f0f4de276dd1e0ff083ea");
db.collection.aggregate({
$match: { // can be skipped but I'd personally keep it because this will use an index on "input._id"/"output._id" (if there is one) to filter out irrelevant documents
$or: [
{ "inbox": { $elemMatch: { "_id": oId } } },
{ "outbox": { $elemMatch: { "_id": oId } } },
]
}
}, {
$project: {
result: {
$concatArrays: [
{ $filter: { "input": "$inbox", "cond": { $eq: [ "$$this._id", oId ] } } },
{ $filter: { "input": "$outbox", "cond": { $eq: [ "$$this._id", oId ] } } }
]
}
}
}, {
$unwind: "$result" // flatten the result array
}, {
$replaceRoot: {
"newRoot": "$result" // move "result" contents all the way up
}
})

MongoDB query with elemMatch for nested array data and return only matching elements

{
"_id" : NumberLong(107),
"cnic" : NumberLong(098765),
"recordsOFGt" : [
{
"records" : [
{
"_id" : NumberLong(1),
"contactIds" : [
NumberLong(303)
],
},
{
"_id" : NumberLong(2),
"contactIds" : [
NumberLong(303),
NumberLong(304)
],
},
{
"_id" : NumberLong(3),
"contactIds" : [
NumberLong(309),
NumberLong(304)
],
},
{
"_id" : NumberLong(4),
"contactIds" : [
NumberLong(303),
NumberLong(304)
],
},
{
"_id" : NumberLong(5),
"contactIds" : [
NumberLong(303),
NumberLong(304)
],
},
]
},
"records2" : {
...
...
}
]
}
I want only record element that will be matched via _id I have tried this
db.getCollection('tempCollection').findOne(
{ 'recordsOFGt': {$elemMatch: {'records._id': 1} }},
{'recordsOFGt.$': 1}
)
this returns all elements of records array need just matching element.
this is what I want as output :
{
"records" :
{
"_id" : NumberLong(1),
"contactIds" : [
NumberLong(303)
],
}
}

Resources