How to make new array from another array during aggregation? - database

I have following document:
{
"subscriptionIds" : [
ObjectId("60c312c6dbb5a49fbbf560ea")
],
"gps" : {
"type" : "Point",
"coordinates" : [
23.942706,
54.932539
]
},
"online" : false,
"suspended" : false,
"hwModel" : "",
"fw" : "",
"lastSeen" : ISODate("2021-06-16T04:43:36.682Z"),
"lastSimRequest" : ISODate("2021-06-16T04:34:59.749Z"),
"lastLocation" : "LT",
"lastLocationType" : "gps",
"createdAt" : ISODate("2021-05-20T10:37:16.025Z"),
"updatedAt" : ISODate("2021-06-11T07:37:56.981Z"),
"notes" : "",
"psk_seed" : "QTAebOeNP4nIs-JJSNNlkAQ78N_VaxOq98-_lQPCyZQ=",
"lastOnline" : ISODate("2021-06-15T08:01:59.886Z"),
"lastOffline" : ISODate("2021-06-16T04:43:36.682Z"),
"onlineReason" : "deviceOnlineStatusFromAC",
"offlineReason" : "deviceOfflineStatusTimeout",
"allocationSettings" : "dataplan",
"subscriptionDataplans" : [
{
"_id" : ObjectId("5fae82fc1224cc8d62b5bf17"),
"organizationId" : ObjectId("5dd63d1c1d042f3018e8374e"),
"organizationName" : "",
"name" : "Naujas plan Telia 75GB",
"enabled" : true,
"contractsId" : [
ObjectId("5e32847ab8013befcc14bb1b"),
ObjectId("5e32847ab8013befcc14bb1b")
],
"simQuota" : 0,
"periodQuota" : NumberLong(0),
"allocationRules" : null,
"createdAt" : ISODate("2020-11-13T12:58:36.650Z"),
"updatedAt" : ISODate("2021-06-14T08:08:28.728Z"),
"notes" : "",
"allowRoaming" : false,
"enablePriorityOrdering" : false,
"priorityOrdering" : ""
},
{
"_id" : ObjectId("5fcf25662b1c7d9bab8c1f7d"),
"organizationId" : ObjectId("5dd63d1c1d042f3018e8374e"),
"organizationName" : "",
"name" : "London test",
"enabled" : true,
"contractsId" : [
ObjectId("5e5dfea1efcf754767408eae")
],
"simQuota" : 0,
"periodQuota" : NumberLong(0),
"createdAt" : ISODate("2020-12-08T07:04:06.255Z"),
"updatedAt" : ISODate("2021-06-15T09:28:07.472Z"),
"notes" : "",
"allowRoaming" : true,
"enablePriorityOrdering" : false,
"priorityOrdering" : ""
}
],
}
Is there a way to make following array using "_id" and "allowRoaming" fields:
"dataplanRoaming": [
{
"_id" : ObjectId("5fae82fc1224cc8d62b5bf17"),
"allowRoaming" : false,
},
{
"_id" : ObjectId("5fcf25662b1c7d9bab8c1f7d"),
"allowRoaming" : true,
}
]
My best result was, I tried using project, addFields etc still can't get structure which I want. Rest of query works just fine just missing this part
"dataplanRoaming" : [
[
false,
true
],
[
ObjectId("5fae82fc1224cc8d62b5bf17"),
ObjectId("5fcf25662b1c7d9bab8c1f7d")
]
],
I hoped that {$addFields:{dataplanRoaming:["$subscriptionDataplans.allowRoaming", "$subscriptionDataplans._id"]}},
would give me wanted result it just made array with _id and allowRoaming as separates fields?
Is there a way to create my wanted result using aggregation etc?

$map to iterate loop of subscriptionDataplans and return needed feidls
db.collection.aggregate([
{
$addFields: {
dataplanRoaming: {
$map: {
input: "$subscriptionDataplans",
in: {
_id: "$$this._id",
allowRoaming: "$$this.allowRoaming"
}
}
}
}
}
])
Playground

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"

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

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
}
]
}

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

$limit number of documents in $lookup

I encounter a problem with this query that returns this result:
{
"_id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"search" : "flarize",
"name" : "flarize",
"color" : 0,
"profil" : "",
"banner" : "",
"desc" : "",
"date" : 1540501286109,
"friend" : [
[
{
"_id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"search" : "flarize",
"name" : "flarize",
"email" : "flarize.b73#gmail.com",
"password" : "$2a$10$eYeOtEkEUyD7TFkjKvhZOuSSpvBolkL17TrPHuoHhOT8JrsQR0UKW",
"color" : 0,
"profil" : "",
"banner" : "",
"desc" : "",
"date" : 1540501286109,
"friend" : [
{
"id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"date" : 1540572026419
},
{
"id" : ObjectId("5bd19a92da24674fdabd26b6"),
"date" : 1540572026419
}
],
"groupes" : [ ]
}
]
]
}
But it's not really what I want, I'd like these fields to be hidden: friend.password, friend.email and the result of friend.groups and friend.friend is limité to 10. I don't know how i can solve this problem. My request :
db.users.aggregate(
{$match:
{search:"flarize"}
},
{$lookup:
{from:"users",
localField:"friend.id",
foreignField:"_id",
as:"friend"
}},
{$project:
{ search: 1,
name: 1,
profil: 1,
banner: 1,
color: 1,
date: 1,
desc: 1,
friend: [{$slice:["$friend", 0, 10]}]
}
}).pretty();
One document of users:
{
"_id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"search" : "flarize",
"name" : "flarize",
"email" : "theo.ba73#gmail.com",
"password" : "$2a$10$eYeOtEkEUyD7TFkjKvhZOuSSpvBolkL17TrPHuoHhOT8JrsQR0UKW",
"color" : 0,
"profil" : "",
"banner" : "",
"desc" : "",
"date" : 1540501286109,
"friend" : [
{
"id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"date" : 1540572026419
},
{
"id" : ObjectId("5bd19a92da24674fdabd26b6"),
"date" : 1540572026419
}
],
"groupes" : [ ]
}
Thank you for helping me.
You can try below aggregation
db.users.aggregate([
{ $match: { search: "flarize" } },
{ $lookup: {
from: "users",
let: { friendId: "$friend.id" },
pipeline: [
{ $match: { $expr: { $in: ["$_id", "$$friendId"] }}},
{ $limit: 10 },
{ $project: { email: 0, password: 0 }}
],
as: "friend"
}}
])

unable to use $pullAll

I have a collection which contains the documents as shown below
{
"_id" : ObjectId("56d92901f9d573cc1c1fb8bb"),
"busEntryExitInformation" : {
"dateTime" : ISODate("2016-03-04T06:19:45.914+0000"),
"busEntryExitEvent" : [
{
"plateNumber" : "ADFN3R2",
"direction" : "EXIT",
"routeNumber" : NumberInt(929),
"driverID" : "DId5",
"driverName" : "john",
"_id" : ObjectId("56d92901f9d573cc1c1fb8c0")
},
{
"plateNumber" : "ADFN3R4",
"direction" : "EXIT",
"routeNumber" : NumberInt(652),
"driverID" : "DId2",
"driverName" : "jack",
"_id" : ObjectId("56d92901f9d573cc1c1fb8bf")
},
{
"plateNumber" : "ADFN3R8",
"direction" : "EXIT",
"routeNumber" : NumberInt(500),
"driverID" : "DId5",
"driverName" : "john",
"_id" : ObjectId("56d92901f9d573cc1c1fb8be")
},
{
"plateNumber" : "ADFN3R7",
"direction" : "ENTRY",
"routeNumber" : NumberInt(500),
"driverID" : "DId3",
"driverName" : "mack",
"_id" : ObjectId("56d92901f9d573cc1c1fb8bd")
},
{
"plateNumber" : "ADFN3R2",
"direction" : "EXIT",
"routeNumber" : NumberInt(652),
"driverID" : "DId2",
"driverName" : "sandesh",
"_id" : ObjectId("56d92901f9d573cc1c1fb8bc")
}
],
"cameraIntrinsics" : {
"cameraFocalLength" : NumberInt(35),
"cameraAngle" : NumberInt(20),
"imageWidth" : "1920",
"imageHeight" : "1080",
"frameRate" : NumberInt(25)
},
"cameraExtrinsics" : {
"cameraId" : NumberInt(1),
"cameraName" : "Under Route-090 NorthboundBridge",
"cameraDirection" : "Towards Northbound Lanes",
"cameraLatitude" : 1.350228,
"cameraLongitude" : 103.984889,
"cameraHeight" : NumberInt(30)
}
},
"__v" : NumberInt(0)
}
}
where busEntryExitEvent is a array i am trying to remove the array elements where direction is exit across all the documents in the collection
result should contain all the documents with direction entry
{
"_id" : ObjectId("56d92901f9d573cc1c1fb8bb"),
"busEntryExitInformation" : {
"dateTime" : ISODate("2016-03-04T06:19:45.914+0000"),
"busEntryExitEvent" : [
{
"plateNumber" : "ADFN3R7",
"direction" : "ENTRY",
"routeNumber" : NumberInt(500),
"driverID" : "DId3",
"driverName" : "mack",
"_id" : ObjectId("56d92901f9d573cc1c1fb8bd")
}
],
"cameraIntrinsics" : {
"cameraFocalLength" : NumberInt(35),
"cameraAngle" : NumberInt(20),
"imageWidth" : "1920",
"imageHeight" : "1080",
"frameRate" : NumberInt(25)
},
"cameraExtrinsics" : {
"cameraId" : NumberInt(1),
"cameraName" : "Under Route-090 NorthboundBridge",
"cameraDirection" : "Towards Northbound Lanes",
"cameraLatitude" : 1.350228,
"cameraLongitude" : 103.984889,
"cameraHeight" : NumberInt(30)
}
},
"__v" : NumberInt(0)
}
}
i am trying to do like this
db.busEntryExitDoc.update(
{ $pull: { busEntryExitEvent: { "direction" : "EXIT"} } },
{ multi: false }
)
this has to be done to all the documents there is no where condition here how to do it please help
The MongoDB update() methods expects three arguments: db.collection.update(query, update, options). If you want to perform the update on all documents, just use an empty object as query:
db.busEntryExitDoc.update({},
{ $pull: { 'busEntryExitInformation.busEntryExitEvent' : {'direction' : "EXIT"} } },
{ multi: true }
);
Also, note the use of the dot notation to access the array field: you have to point the $pull operator to an array otherwise the operation fails. Finally, use { multi: true } as options since you want to update all the documents in your collection.
You are doing it wrong the first argument to .update() is the "query" argument which should be an empty document here.
db.busEntryExitDoc.update(
{},
{ $pull: { "busEntryExitInformation.busEntryExitEvent": { "direction": "EXIT" } } },
{ multi: true }
)
The same thing apply to the .updateMany() method
db.busEntryExitDoc.update(
{},
{ $pull: { "busEntryExitInformation.busEntryExitEvent": { "direction": "EXIT" } } },
)

Resources