RSKMR
RSKMR

Reputation: 1892

Node + Mongodb + sort nested array

I am using node with mongodb.I try to sort nested array.

Example json in monogodb.

{
    "items": [
        {
            "name": "A",
            "order": 3
        }, {
            "name": "B",
            "order": 2
        }, {
            "name": "C",
            "order": 1
        }, {
            "name": "D",
            "order": 4
        }
    ],
    "name": "Test",
        "_id" : 01245678913
}
{
    "items": [
        {
            "name": "A",
            "order": 3
        }, {
            "name": "B",
            "order": 2
        }, {
            "name": "C",
            "order": 1
        }, {
            "name": "D",
            "order": 4
        }
    ],
    "name": "Test",
        "_id" : 098765432134
}

I am expecting result should display based on order. items.order

Here possible to pass ID. If get Id means display the result for the respective Id. otherwise need to show all lists.

I attached my node code:

router.post('/get', function(req, res, next) {

        var results = {
            resp : {},
            id : null,
            query : {}
        };

        if (!( typeof req.body['id'] === 'undefined' || req.body['id'] === null )) {
            results.id = req.body['id'];
        }

        Q(results).then(function(results) {
            var deferred = Q.defer();
            var collection = mongoUtil.list;
            if (results.id != null) {
                results.query._id = ObjectId(results.id);
            }


            collection.find(results.query).toArray(function(err, lists) {

                if (!err && lists.length > 0) {
                    results.resp.lists = lists;
                    deferred.resolve(results);
                } else {

                    results.resp.message = 'No List';
                    results.resp.debug = err;
                    deferred.reject(results);
                }
            });
            return deferred.promise;
        }).then(function(results) {
            results.resp.message = 'Result found';
            results.resp.status = 'Success';
            res.send(results.resp);
        }).fail(function(results) {
            results.resp.status = 'Error';
            res.send(results.resp);
        });

    });

I found few example they using aggregate function.

collection.aggregate([
  {$unwind: "$answers"}, 
  {$sort: {"item.order":1}}, 
  {$group: {_id:"$_id", answers: {$push:"$answers"}}}
]);

Here little bit confusing.

Upvotes: 2

Views: 2108

Answers (1)

Vikash Kumar
Vikash Kumar

Reputation: 1111

Aggregations operations process data records and return computed results. Aggregation operations group values from multiple documents together, and can perform a variety of operations on the grouped data to return a single result.

Try this -

collection.aggregate([
  { $unwind: "$items" },
  { $sort: { "items.order": 1 } },
  { $group: { _id: "$_id", items: { $push: "$items" } } }
]);

db.collection.aggregate(pipeline, options):- Calculates aggregate values for the data in a collection.

Pipeline $unwind (aggregation) stage:- Deconstructs an array field from the input documents to output a document for each element. Each output document is the input document with the value of the array field replaced by the element.

Examples-

Consider an inventory items with the following document:

{ "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] }

The following aggregation uses the $unwind stage to output a document for each element in the sizes array:

db.items.aggregate( [ { $unwind : "$sizes" } ] )

The operation returns the following results:

{ "_id" : 1, "item" : "ABC1", "sizes" : "S" } { "_id" : 1, "item" : "ABC1", "sizes" : "M" } { "_id" : 1, "item" : "ABC1", "sizes" : "L" }

Pipeline $sort (aggregation) stage:- Sorts all input documents and returns them to the pipeline in sorted order.

The $sort stage has the following prototype form:

{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }

Examples-

For the field or fields to sort by, set the sort order to 1 or -1 to specify an ascending or descending sort respectively, as in the following example:

db.users.aggregate( [ { $sort : { age : -1, posts: 1 } } ] )

Pipeline $group (aggregation) stage:- Groups documents by some specified expression and outputs to the next stage a document for each distinct grouping. The output documents contain an _id field which contains the distinct group by key. $group does not order its output documents.

The $group stage has the following prototype form:

{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }

Accumulator $push:- Returns an array of all values that result from applying an expression to each document in a group of documents that share the same group by key.

$push has the following syntax:

{ $push: <expression> }

$push is only available in the $group stage.

For more reference see this link - https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/

Upvotes: 1

Related Questions