Sorting objects in array within mongodb - mongodb

I've seen this question all over google/SO/mongo docs, and I've tried to implement the solution, but it's not working for me. I have the following test database:
> db.test.find().pretty()
{
"_id" : ObjectId("56b4ab167db9acd913ce6e07"),
"state" : "HelloWorld",
"items" : [
{
"guid" : "123"
},
{
"guid" : "124"
},
{
"guid" : "123"
}
]
}
And I want to sort by the "guid" element of items. Running the sort commands yields:
> db.test.find().sort( {"items.guid" : 1}).pretty()
{
"_id" : ObjectId("56b4ab167db9acd913ce6e07"),
"state" : "HelloWorld",
"items" : [
{
"guid" : "123"
},
{
"guid" : "124"
},
{
"guid" : "123"
}
]
}
How can I sort by the "guid" element, so that the returned output of "items" is the 123, 123, and 124 guids (essentially move the child elements of "items" so that they're sorted by "guid")?
EDIT: I've also tried to use the $orderby command, doesn't accomplish what I want:
> db.test.find({ $query : {}, $orderby: {'items.guid' : 1} }).pretty()
{
"_id" : ObjectId("56b4ab167db9acd913ce6e07"),
"state" : "HelloWorld",
"items" : [
{
"guid" : "123"
},
{
"guid" : "124"
},
{
"guid" : "123"
}
]
}

Here is how it can be done using aggregate
db.test.aggregate([
{
$unwind : '$items'
},
{
$sort : {'items.guid' : 1}
},
{
$group : {
_id : '$_id',
state : {$first : '$state'},
items : {
$push : {'guid' : '$items.guid'}
}
}
}
]).pretty()
This is the output from this command.
{
"_id" : ObjectId("56b4ab167db9acd913ce6e07"),
"state" : "HelloWorld",
"items" : [
{
"guid" : "123"
},
{
"guid" : "123"
},
{
"guid" : "124"
}
]
}

Related

MongoDB - Find duplicated elements in record property

I'm struggling to identified duplicated elements in my MongoDB records, here is my problem :
I have a Mongo collection named "elements".
Example of a record in this collection :
{
"_id" : ObjectId("5d1b2204e851271e80c824b6"),
"name" : "A",
"items" : [
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d7"),
"_id" : ObjectId("5d1b2205e851271e80c82534")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d6"),
"_id" : ObjectId("5d1b2205e851271e80c82533")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d8"),
"_id" : ObjectId("5d1b2205e851271e80c82532")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d5"),
"_id" : ObjectId("5d1b3048e851271e80c826a5")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d5"),
"_id" : ObjectId("5d1b3048e851271e80c826ad")
}
]
}
I would like to identify records where the array "items" contains objects with the same "ref_id".
In my example we can see that the last two objects of the "items" array have the same "ref_id" : ObjectId("5d1b2204e851271e80c823d5").
I tried a bunch of aggregate function but unfortunately couldn't came out with a solution.
The following query can get us the expected output:
db.elements.aggregate([
{
$unwind:"$items"
},
{
$group:{
"_id":"$_id",
"root":{
$first:"$$ROOT"
},
"items":{
$push:"$items"
},
"distinctItems":{
$addToSet: "$items.ref_id"
}
}
},
{
$match:{
$expr:{
$ne:[
{
$size:"$items"
},
{
$size:"$distinctItems"
}
]
}
}
},
{
$addFields:{
"root.items":"$items"
}
},
{
$replaceRoot:{
"newRoot":"$root"
}
}
]).pretty()
Data set:
{
"_id" : ObjectId("5d1b2204e851271e80c824b6"),
"name" : "A",
"items" : [
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d7"),
"_id" : ObjectId("5d1b2205e851271e80c82534")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d6"),
"_id" : ObjectId("5d1b2205e851271e80c82533")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d8"),
"_id" : ObjectId("5d1b2205e851271e80c82532")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d5"),
"_id" : ObjectId("5d1b3048e851271e80c826a5")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d5"),
"_id" : ObjectId("5d1b3048e851271e80c826ad")
}
]
}
{
"_id" : ObjectId("5d654b9d7d0ab652c42315f2"),
"name" : "B",
"items" : [
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d7"),
"_id" : ObjectId("5d1b2205e851271e80c82534")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d6"),
"_id" : ObjectId("5d1b2205e851271e80c82533")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d8"),
"_id" : ObjectId("5d1b2205e851271e80c82532")
}
]
}
Output:
{
"_id" : ObjectId("5d1b2204e851271e80c824b6"),
"name" : "A",
"items" : [
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d7"),
"_id" : ObjectId("5d1b2205e851271e80c82534")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d6"),
"_id" : ObjectId("5d1b2205e851271e80c82533")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d8"),
"_id" : ObjectId("5d1b2205e851271e80c82532")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d5"),
"_id" : ObjectId("5d1b3048e851271e80c826a5")
},
{
"ref_id" : ObjectId("5d1b2204e851271e80c823d5"),
"_id" : ObjectId("5d1b3048e851271e80c826ad")
}
]
}
Explanation: We are populating an array of distinct ref_id from each document and matching if the size of the populated array is equal to the size of actual items array.

MongoDB - query for a nested item inside a collection

i have a mongodb collection "result" with data like
{ "_id" : {
"user" : "Howard",
"friend" : "Sita"
},
"value" : {
"mutualFriend" :[ "Hanks", "Bikash", "Shyam", "Bakshi" ]
}
}
{ "_id" : {
"user" : "Shiva",
"friend" : "Tom"
},
"value" : {
"friendList" :[ "Hanks", " Tom", " Karma", " Hari", " Dinesh" ]
}
}
{ "_id" : {
"user" : "Hari",
"friend" : "Shiva"
},
"value" : {
"mutualFriend" :[ "Tom", "Karma", "Dinesh" ]
}
}
Now, here i want to query whole Document having value.mutualFriend. how can i get the result?
Expected Output
{ "_id" : {
"user" : "Howard",
"friend" : "Sita"
},
"value" : {
"mutualFriend" :[ "Hanks", "Bikash", "Shyam", "Bakshi" ]
}
}
{ "_id" : {
"user" : "Hari",
"friend" : "Shiva"
},
"value" : {
"mutualFriend" :[ "Tom", "Karma", "Dinesh" ]
}
}
i have large number of document in MongoDB collection, containing value.friendList and value.mutualFriend and then i want to find only documents with value.mutualFriend
db.collection.find({"value.mutualFriend.0" : { $exists : true }})
Its just make sure that the 0th element exists. you can customize your query over various array length.

Sort the array in the document with MongoDB

I have data structure from mongoDb v 3.2
I will try make sorting date by month and sorting within statistic array through aggregation-framework
Source data:
"monthStart" : "2015-11",
"monthEnd" : "2015-11",
"date" : ISODate("2016-03-09T09:06:58Z"),
"statistic" : [
{
"name" : "site1.com",
"ga" : "99999",
"data" : {
"desktop" : {
"users" : NumberLong(25),
"pageviews" : NumberLong(56789),
}
}
},
{
"name" : "site2.com",
"ga" : "102",
"data" : {
"desktop" : {
"users" : NumberLong(21),
"pageviews" : NumberLong(9399393),
}
}
},
{
"name" : "site3.com",
"ga" : "103",
"data" : {
"desktop" : {
"users" : NumberLong(103),
"pageviews" : NumberLong(9399393),
}
}
},
{
"monthStart" : "2015-12",
"monthEnd" : "2015-12",
"date" : ISODate("2016-03-09T09:08:39Z"),
"statistic" : [
{
"name" : "site1.com",
"ga" : "9999",
"data" : {
"desktop" : {
"users" : NumberLong(88),
"pageviews" : NumberLong(83838),
},
}
},
{
"name" : "site2.com",
"ga" : "8888",
"data" : {
"desktop" : {
"users" : NumberLong(75),
"pageviews" : NumberLong(77777777),
},
}
},
{
"name" : "site3.com",
"ga" : "103",
"data" : {
"desktop" : {
"users" : NumberLong(25),
"pageviews" : NumberLong(9399393),
}
}
},
}
]
How I can get structure sorting within array statistic?
Expected result :
"monthStart" : "2015-11",
"monthEnd" : "2015-11",
"date" : ISODate("2016-03-09T09:06:58Z"),
"statistic" : [
{
"name" : "site3.com",
"ga" : "103",
"data" : {
"desktop" : {
"users" : NumberLong(103),
"pageviews" : NumberLong(9399393),
}
}
},
{
"name" : "site2.com",
"ga" : "102",
"data" : {
"desktop" : {
"users" : NumberLong(21),
"pageviews" : NumberLong(9399393),
}
}
},
{
"name" : "site1.com",
"ga" : "99999",
"data" : {
"desktop" : {
"users" : NumberLong(25),
"pageviews" : NumberLong(56789),
}
}
},
{
"monthStart" : "2015-12",
"monthEnd" : "2015-12",
"date" : ISODate("2016-03-09T09:08:39Z"),
"statistic" : [
{
"name" : "site3.com",
"ga" : "103",
"data" : {
"desktop" : {
"users" : NumberLong(201),
"pageviews" : NumberLong(9399393),
}
}
},
{
"name" : "site1.com",
"ga" : "9999",
"data" : {
"desktop" : {
"users" : NumberLong(88),
"pageviews" : NumberLong(83838),
},
}
},
{
"name" : "site2.com",
"ga" : "8888",
"data" : {
"desktop" : {
"users" : NumberLong(75),
"pageviews" : NumberLong(77777777),
},
}
},
}
]
I tried make, but it is didn't work:
db.TrafficStatistic.aggregate([
{ "$unwind": "$statistic" },
{ "$sort": { "statistic.data.desktop.users": 1 } } ])
I see the problem. People are searching for and finding this stackoverflow answer:
how to sort array inside collection record in mongoDB
It's wrong, since it never "reconstructs" the array.
You do that with $group and $push, and since you are grouping you will want $first for the other fields in the document you want:
db.TrafficStatistic.aggregate([
{ "$unwind": "$statistic" },
{ "$sort": { "_id": 1, "statistic.data.desktop.users": 1 } },
{ "$group": {
"_id": "$_id",
"monthStart" : { "$first": "$monthStart" },
"monthEnd" : { "$first": "$monthEnd" },
"date" : { "$first": "$date" },
"statistic": { "$push": "$statistic" }
}}
])
Note also the $sort is applied to both the "_id" and the other field to sort. This is so the sorting is applied per document and is important when the document details are put back together in $group.
Now the document looks the same as it did, but this time the array members are sorted.

how to get this query in mongoDB

I have this collection...
> db.banks.find().pretty()
{
"_id" : ObjectId("54f37cbb44aec3b01b7db8f4"),
"name" : "A",
"branches" : [
{
"branch_id" : 8561,
"name" : "X",
},
{
"branch_id" : 8576,
"name" : "Y",
}
]
}
{
"_id" : ObjectId("54f37cbb44aec3b01b7db8f5"),
"name" : "B",
"branches" : [
{
"branch_id" : 3238,
"name" : "Z",
}
]
}
with this command :
db.banks.aggregate({$project{"branches.name":1,"_id":0}});
get this result :
{ "branches" : { { "name" : "X" }, { "name" : "Y" } } }
{ "branches" : { { "name" : "Z" } } }
but; how I get this result?
(In fact, one object and without "branches".)
{{"name" : "X"}, {"name" : "Y"}, {"name" : "Z"}}
very thanks...
One way you could go about this is to do an $unwind first in the aggregation pipeline to get a deconstructed array with a document for each element and then group by the array element $branches.name:
db.banks.aggregate([
{ $unwind: '$branches'},
{
$group: {
_id: {
name: '$branches.name'
}
}
},
{
$project: {
_id: 0,
name: '$_id.name'
}
},
{ $sort : { "name" : 1 } }
])
Outputs:
{
"result" : [
{
"name" : "X"
},
{
"name" : "Y"
},
{
"name" : "Z"
}
],
"ok" : 1
}

In MongoDb, how to apply sort internal fields present in document?

My document looks like this
{
field1: somevalue,
name:xtz
nested_documents: [ // array of nested document
{ x:"1", y:"2" }, // first nested document
{ x:"2", y:"3" }, // second nested document
{ x:"-1", y:"3" }, // second nested document
// ...many more nested documents
]
}
How one can sort the data present in nested_documents?
Expected answer is shown below:
nested_documents: [ { x:"-1", y:"3" },{ x:"1", y:"2" },{ x:"2", y:"3" }]
To do this you would have to use the aggregation framework
db.test.aggregate([{$unwind:'$nested_documents'},{$sort:{'nested_documents.x':
1}}])
this returns
"result" : [
{
"_id" : ObjectId("5139ba3dcd4e11c83f4cea12"),
"field1" : "somevalue",
"name" : "xtz",
"nested_documents" : {
"x" : "-1",
"y" : "3"
}
},
{
"_id" : ObjectId("5139ba3dcd4e11c83f4cea12"),
"field1" : "somevalue",
"name" : "xtz",
"nested_documents" : {
"x" : "1",
"y" : "2"
}
},
{
"_id" : ObjectId("5139ba3dcd4e11c83f4cea12"),
"field1" : "somevalue",
"name" : "xtz",
"nested_documents" : {
"x" : "2",
"y" : "3"
}
}
],
"ok" : 1
Hope this helps