2

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.

2
  • The aggregate you are suggesting looks good to me. What went wrong? Commented May 6, 2016 at 7:13
  • The above code not working for me. ====>>>> collection.aggregate([ {$unwind: "$answers"}, {$sort: {"item.order":1}}, {$group: {_id:"$_id", answers: {$push:"$answers"}}} ]); Commented May 6, 2016 at 7:40

1 Answer 1

1

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/

Sign up to request clarification or add additional context in comments.

1 Comment

@RSKMR, I hope this will clear your confusion a little bit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.