2

I have documents in MongoDB, like so:

{
    "_id" : ObjectId("5a748c8b178227d602ec9ce8"),
    "dateHour" : ISODate("2018-02-02T16:00:00.000Z"),
    "data" : [ 
        {
            "date" : ISODate("2018-02-02T16:06:35.033Z"),
            "cap" : 437105726836.0
        }, 
        {
            "date" : ISODate("2018-02-02T16:09:25.127Z"),
            "cap" : 437316498502.0
        },
        ...
    ]
}

Using aggregate method (in NodeJS):

db.getCollection('hourly').aggregate([
    {$match: {}}, 
    {$unwind: "$data"}, 
    {$project: {_id: 0, date: "$data.date", cap: "$data.cap" } }
])

I get output like:

[
    {
        "date" : ISODate("2018-02-02T16:06:35.033Z"),
        "cap" : 437105726836.0
    },
    {
        "date" : ISODate("2018-02-02T16:09:25.127Z"),
        "cap" : 437316498502.0
    }
]

QUESTION: What is the most effective way to get output like so:

[
    [ISODate("2018-02-02T16:06:35.033Z"), 437105726836.0],
    [ISODate("2018-02-02T16:09:25.127Z"), 437316498502.0]
]

?

I can simply add .map(function(item) {return [item.date, item.cap]}) but is this most effective way when working with huge amount of data?

3 Answers 3

2

try $project with $map or $reduce

$map

db.col.aggregate(
    [
        {$project : {
            _id : 0, 
            data : {$map : {input : "$data", as : "d", in : ["$$d.date", "$$d.cap"]}}
            }
        }
    ]
)

$reduce

db.col.aggregate(
    [
        {$project : {
            _id : 0, 
                data : {$reduce : {input : "$data", initialValue : [], in : {$concatArrays : ["$$value", [["$$this.date", "$$this.cap"]]]}}}
            }
        }
    ]
).pretty()

output

{
    "data" : [
        [
            ISODate("2018-02-02T16:06:35.033Z"),
            437105726836
        ],
        [
            ISODate("2018-02-02T16:09:25.127Z"),
            437316498502
        ]
    ]
}
Sign up to request clarification or add additional context in comments.

Comments

0

The root has to be a document, proof:

db.test.aggregate([
    {$unwind: "$data"}, 
    { $replaceRoot: { newRoot: ["$data.date", "$data.cap"] } }
]);
assert: command failed: {
        "ok" : 0,
        "errmsg" : "'newRoot' expression must evaluate to an object, but resulting value was: [null, null]. Type of resulting value: 'array'. Input document: {date: 2018-02-02T16:06:35.033Z, cap: 4.37106e+11}",
        "code" : 40228,
        "codeName" : "Location40228"
} : aggregate failed

You could, however, project it into an array within a document:

> db.test.aggregate([
...     {$unwind: "$data"},
... { $replaceRoot: { newRoot: {a:["$data.date", "$data.cap"] } }}
... ])
{ "a" : [ ISODate("2018-02-02T16:06:35.033Z"), 437105726836 ] }
{ "a" : [ ISODate("2018-02-02T16:09:25.127Z"), 437316498502 ] }

Comments

0

It's in the projection. Try this:

db.getCollection('hourly').aggregate([
   {$match: {}}, 
   {$unwind: "$data"}, 
   {$project: {_id: 0, date: ["$data.date", "$data.cap"] } }
]);

Just in case my syntax is a little off, here is MongoDb documentation to project a new array.

I don't see why you need aggregate.

Why not:

db.getCollection('hourly').find({}, {data: 1}, (err, results) => {
   // manage results here.
});

3 Comments

On your first aggregate, result like so: [ {date: [ISODate("2018-02-02T16:06:35.033Z"), 437105726836.0]}, {date: [ISODate("2018-02-02T16:09:25.127Z"), 437316498502.0]} ]
On second request result also not useful, like so: { "data" : [ { "date" : ISODate("2018-02-02T16:06:35.033Z"), "cap" : 437105726836.0, }, { "date" : ISODate("2018-02-02T16:09:25.127Z"), "cap" : 437316498502.0, }, ... }, { "data" : [ { "date" : ISODate("2018-02-02T16:06:35.033Z"), "cap" : 437105726836.0, }, ...
On the first one, what's the problem? It has your fields in an array of arrays, which looks like what you are seeking. On the second one, it looks like you did not paste all of it. So, why can't you use this format? Maybe you can edit your question and explain.

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.