MongoDb query to find specific object in nested array - arrays

i have an array of object player_of_day inwhich there is again array of user-Ids i.e. nominate_by I want to find an object having maximum count.
Something like-
an object from player_of_day whose count is maximum
"player_of_day" : [
{
"nominate_by" : [
ObjectId("58994bca4187b412aec50c94"),
ObjectId("58994a124187b412aec50c91"),
ObjectId("589955d54187b412aec50c99")
],
"nominate_to" : ObjectId("58994b374187b412aec50c93"),
"count" : 3
},
{
"nominate_by" : [
ObjectId("58994c254187b412aec50c95"),
ObjectId("58994ad04187b412aec50c92")
],
"nominate_to" : ObjectId("58994a124187b412aec50c91"),
"count" : 2
},
{
"nominate_by" : [
ObjectId("58994b374187b412aec50c93")
],
"nominate_to" : ObjectId("58994c254187b412aec50c95"),
"count" : 1
}
],

you can use $unwind
db.match.aggregate([{"$unwind":"$player_of_day"},{"$sort":{'player_of_day.count':-1}},{"$limit":1}]);

Related

Update nested array in a mongo document

I have below collection
{
"_id" : ObjectId("5d7e6c54c23c210001108556"),
“parentId" : "5d0162ba69cf130001a16115",
"tasks" : [
{
"_id" : "ae60a8f1",
"taskMetaDataIds” : [
ObjectId("5d55a648e2f7320001e578ac")
],
"name" : “meta 3"
},
{
"_id" : "07544d96",
"taskMetaDataIds" : [
ObjectId("5d55a648e2f732676676676”),
ObjectId("5d55a648e2612333556888”)
],
"name" : “meta 2"
},
],
"name" : “New Topic",
"createdBy" : "01526151-8303-450f-b08b-b36a1760b774",
"createdDate" : ISODate("2019-09-15T16:52:36.150+0000"),
"updatedDate" : ISODate("2019-09-15T16:52:36.150+0000")
}
I am looking for below output . Is there an operator which can directly convert the array of objects into array of strings as shown below. I can do it with a script by looping over the taskMetaDataIds array but I am looking to use a direct mongo operator which suits my purpose.
{
"_id" : ObjectId("5d7e6c54c23c210001108556"),
“parentId" : "5d0162ba69cf130001a16115",
"tasks" : [
{
"_id" : "ae60a8f1",
"taskMetaDataIds” : [
"5d55a648e2f7320001e578ac"
],
"name" : “meta 3"
},
{
"_id" : "07544d96",
"taskMetaDataIds" : [
"5d55a648e2f732676676676”,
“5d55a648e2612333556888”
],
"name" : “meta 2"
},
],
"name" : “New Topic",
"createdBy" : "01526151-8303-450f-b08b-b36a1760b774",
"createdDate" : ISODate("2019-09-15T16:52:36.150+0000"),
"updatedDate" : ISODate("2019-09-15T16:52:36.150+0000")
}
I tried below but it does not seem to be working-
db.getCollection("data").updateOne({"_id":ObjectId("5d7e6c54c23c210001108556")}, [{ $set: { "tasks.taskMetaDataIds": "$tasks.taskMetaDataIds.str" } }])
$set - Set tasks array field.
1.1. $map - Iterate each element in the tasks array and return a new array.
1.1.1. $mergeObjects - Merge the current iterated task object and taskMetaDataIds array (from the result 1.1.1.1).
1.1.1.1. $map - Iterate the current iterated task object's taskMetaDataIds array and returns a new array.
1.1.1.1.1. $toString - Convert each iterate id from ObjectId type to string type.
db.getCollection("data").updateOne({
"_id": ObjectId("5d7e6c54c23c210001108556")
},
[
{
$set: {
"tasks": {
$map: {
input: "$tasks",
as: "task",
in: {
$mergeObjects: [
"$$task",
{
"taskMetaDataIds": {
$map: {
input: "$$task.taskMetaDataIds",
in: {
$toString: "$$this"
}
}
}
}
]
}
}
}
}
}
])
Demo # Mongo Playground

Compare array within objects in an array of the same Mongo document

I have a Mongo database with multiple documents and they all contain 2 Items for in store and online locations. The difference will be that attributes within the items object may differ. I am trying to capture all documents that have differing attributes between the object items with the array.
I've tried using $expr and comparing the position of the elements such as "Items.0.Attributes" == "Items.1.Attributes" but had no luck.
{
"ID" : "123456789",
"Items" : [
{
"ItemDept" : "softLines",
"ProductId" : {
"Name" : "shirts",
"_id" : "12345Shirts"
},
"Attributes" : [ "blue","small","mens"],
"Season" : "Summer"
"Location":"online"
}
,
{
"ItemDept" : "softlines",
"ProductId" : {
"Name" : "shirts",
"_id" : "12345Shirts")
},
"Attributes" : [ "blue","small","women"],
"Season" : "Summer"
"Location":"stores"
}
]
}
If I understand what you want to find/output, here's one way you could do it.
db.collection.find({
"$expr": {
"$not": {
"$setEquals": [
{"$first": "$Items.Attributes"},
{"$last": "$Items.Attributes"}
]
}
}
})
Try it on mongoplayground.net.

In mongo db, how can I set a value in an array of arrays without knowing the index?

In Mongo DB, how can I set values in an array of arrays when the index cannot be assumed?
For example, how can I set the IdleShutdown value to "2" (instead of "10") in this blob below?
What would the command look like to correctly find the item in the list and set the value without any assumptions that the current index will stay the same? I also cannot assume any values for the second item in the list (eg, "10" could become any value)
> db.EventPluginSettingsCollection.findOne({"_id": "spot"})
{
"_id" : "spot",
"LastWriteTime" : ISODate("2019-12-16T11:04:30.499Z"),
"Name" : "Spot",
"PluginEnabled" : 1,
"DebugLogging" : false,
"Icon" : null,
"Limits" : [ ],
"DlInit" : [
[
"State",
"Disabled"
],
[
"Config",
"{}"
],
[
"IdleShutdown",
"10"
],
[
"StaggerInstances",
"50"
],
[
"PreJobTaskMode",
"Conservative"
],
[
"AWSInstanceStatus",
"Disabled"
]
],
"Meta" : {
}
}
I understand I could replace the whole blob, and I could also use individual indexes for each item, but none of these approaches are future proof should the number of items in the list change in the future.
MongoDB 3.6 introduced the filtered positional operator array update operator, $[ < identifier> ], for these types of operations. Updates using this syntax will only update elements of an array that match a specified array filter.
For example:
> db.foo.update(
... { "_id" : "spot" },
... {
... "$set" : {
... // only updates array elements matching the filter below
... "DlInit.$[element]" : [ "IdleShutdown", "2"]
... }
... },
... {
... "arrayFilters": [
... // Search for DlInit array elements that are the specified array
... { "element.0" : "IdleShutdown" }
... ]
... }
... )
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.foo.find().pretty()
{
"_id" : "spot",
"LastWriteTime" : ISODate("2019-12-16T11:04:30.499Z"),
"Name" : "Spot",
"PluginEnabled" : 1,
"DebugLogging" : false,
"Icon" : null,
"Limits" : [ ],
"DlInit" : [
[
"State",
"Disabled"
],
[
"Config",
"{}"
],
[
"IdleShutdown",
"2"
],
[
"StaggerInstances",
"50"
],
[
"PreJobTaskMode",
"Conservative"
],
[
"AWSInstanceStatus",
"Disabled"
]
],
"Meta" : {
}
}

Query for deeply nested array in mongodb

How do I query a deeply nested docs like show in the below image.
Here columns is an array of unknown size. Each element in the column contains a record that is again an array. Each element of the record array contains an array called fields. Each entry in the field contains 2 keys called name and value.
I'm querying the name of the innermost array (in fields array). I couldn't go above level 1 order of nesting.
JSON doc of the above image
"data" : {
"columns" : [
{
"name" : "styleId",
"record" : [
{
"fname" : "column_mapping",
"_id" : ObjectId("5ba488c79dc6d62c90257752"),
"fields" : [
{
"name" : "column_mapping_form",
"value" : "styleId"
}
],
"rules" : [
[
]
]
}
]
},
{
"name" : "vendorArticleNumber",
"record" : [
{
"fname" : "column_mapping",
"_id" : ObjectId("5ba488c79dc6d62c90257753"),
"fields" : [
{
"name" : "column_mapping_form",
"value" : "vendorArticleNumber"
}
],
"rules" : [
[
]
]
}
]
},
{
"name" : "vendorArticleName",
"record" : [
{
"fname" : "column_mapping",
"_id" : ObjectId("5ba488c79dc6d62c90257754"),
"fields" : [
{
"name" : "column_mapping_form",
"value" : "vendorArticleName"
}
],
"rules" : [
[
]
]
}
]
}
}
What can be the solutions if such kind of heaving nesting is there?
db.collection.find("data.columns.record.fields.name" : "column_mapping_form")
will match all documents where there is at least one element of columns has at least one record with at least one field where name is "column_mapping_form".
https://docs.mongodb.com/manual/tutorial/query-array-of-documents/ has very good explanation, examples, and interactive shell to play with.

mongoDB Array length on children element [duplicate]

This question already has answers here:
MongoDB: count the number of items in an array
(3 answers)
Closed 5 years ago.
I have a data similar to the below in my mongo DB. Obviously the length of array1 is two and I am looking on a way to count the length of such array with mongo db script. Thanks
{
"_id" : ObjectId("65465465465465465468"),
"header" : {
"test" : "test",
},
"value" : 11.763548134011048,
"array1" : [
{
"q" : {
"value" : 250
}
},
{
"q" : {
"value" : 30,
}
}
],
"array2" : [ ]
}
You can use the $size aggregation operator.
Given the document you showed in your OP, the following command ...
db.collection.aggregate(
[
{
$project: {
sizeOfArray1: { $size: "$array1" }
}
}
]
)
... will return:
{
"_id" : ObjectId("65465465465465465468"),
"sizeOfArray1" : 2
}
This approach is valid for all versions of Mongo >= 2.6.
Update: in response to this comment ...
If I have more nested objects until I reach to my array I can use they same code and I just change the name of the field to the item that I am interested in?
You address any document attribute using path notation with a . to denote each 'level'. So, if your document looked like this:
{
"_id" : ObjectId("65465465465465465468"),
"header" : {
"test" : "test",
"array" : [1, 2, 3]
},
"value" : 11.763548134011048,
"array1" : [
{
"q" : {
"value" : 250
}
},
{
"q" : {
"value" : 30,
}
}
],
"array2" : [ ]
}
... then the following command would return the count of the array field inside the header nested sub document:
db.collection.aggregate(
[
{
$project: {
sizeOfHeaderArray: { $size: "$header.array" }
}
}
]
)
So, perhaps you can now see that you would address the array field inside the header nested sub document using header.array.
Hope that helps.

Resources