Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort by values of documents in nested arrays in Mongo

I have a collection called Objects. Each Object document has a nested array of documents called properties. Each property document has a name and a value.

For example, let's say I have these two objects, each having two properties (height and width). How would I sort the objects by height?

{
  "id": 1,
  "properties": [
    {
      "name": "height",
      "value": 170
    },
    {
      "name": "width",
      "value": 200
    },
  ]
},
{
  "id": 2,
  "properties": [
    {
      "name": "height",
      "value": 100
    },
    {
      "name": "width",
      "value": 300
    },
  ]
}
like image 634
Marjan Avatar asked Sep 08 '14 16:09

Marjan


People also ask

How to sort nested array in MongoDB?

MongoDB query to sort nested array? To sort nested array in MongoDB, use $ sort. Let us create a collection with documents − > db.demo505.insertOne( ... { ... "details": [ ...

How to sort multiple fields in MongoDB marks document?

Sort documents in descending order according to the total field of the marks document: In MongoDB, we can also sort multiple fields using sort () method. In this method, you should declare multiple fields that you want to sort.

How do I filter an array field in MongoDB?

Usually when you make queries in MongoDB, the returned result is the whole document with all the fields unless you make a projection. However, sometimes you may want to filter some field, specifically an array field by a certain condition. There’re 3 options to achieve this: $elemMatch can be used in find operations.

How do you sort an array of elements in Python?

The $sortArray syntax and semantics are the same as the behavior in a $push operation modified by $sort. If the array elements are documents, you can sort by a document field. Specify the field name and a sort direction, ascending ( 1 ), or descending ( -1 ).


1 Answers

In most cases, MongoDB's aggregation framework is your friend whenever you are dealing with arrays. Take a look at the $unwind operator that can be use to break the array into individual documents. I've posted a sample query below to sort the documents by height. Note that you can use the $project operator in the aggregation pipeline to better format the results.

db.objects.aggregate([
    // De-normalize the 'properties' array
    {$unwind:"$properties"}, 
    // Filter for only height
    {$match:{"properties.name":"height"}},
    // Sort by 'height' in ascending order.  Use -1 for descending 
    {$sort:{"properties.value":1}}
])

EDIT: One way to keep the properties element intact is to make a copy of it just to be used for sorting. An example is below:

db.objects.aggregate([
    // Make a copy of the 'properties' element
    {$project:{properties:1, sortfield:"$properties"}}, 
    {$unwind:"$sortfield"}, 
    {$match:{"sortfield.name":"height"}}, 
    {$sort:{"sortfield.value":1}}, 
    // Get rid of 'sortfield' 
    {$project:{properties:1}}
])
like image 109
Anand Jayabalan Avatar answered Sep 23 '22 09:09

Anand Jayabalan