wzf1943
wzf1943

Reputation: 141

How to trim MongoDB aggregate result's one field

This is my data structure store in DB

{
    "_id" : ObjectId("58a4e451c164f95c98e96235"),
    "_class" : "com.contix.log.parser.log.Log",
    "vin" : "6",
    "esn" : "c",
    "volt" : 11.32,
    "internVolt" : 4.14,
    "temp" : 39.49,
    "timestamp" : NumberLong("1483375743285")
}

What I want to do is get latest 10 unique volt, internVolt, temp based on vin and esn String. Also needs latest timestamp. Then I'm trying to use mongo aggregate way to get right result.

db.log.aggregate({$sort:{timestamp:-1}},{$group:{_id : {esn:"$esn",vin:"$vin"},firstTimestamp:{$first:"$timestamp"},volts:{$addToSet:"$volt"}}},{$limit:5})

But this is my result looks like

{ "_id" : { "esn" : "b", "vin" : "2" }, "firstTimestamp" : NumberLong("1485852368147"), "volts" : [ 11.95, 10.08, 10.77, 10.47, 11.41, 10.36, 10.96, 10.75, 10.39, 10.53, 10.1, 10.22, 11.16, 10.11, 11.87, 11.33, 11.82, 11.78, 10.25, 11.86, 10.5, 10.41, 11.3, 11.31, 11.97, 10.64, 11.57, 10.93, 10.02, 10.68, 10.9, 11.53, 10.46, 11.42, 11.73, 11.32, 10.19, 10.51, 11.35, 11.28, 10.65, 10.21, 11.18, 10.91, 11.43, 10.52, 11.34, 11.1, 10.99, 10.61, 10.28, 10.97, 10.3, 10.31, 11.81, 11.8, 10.42, 11.51, 10.72, 11.39, 10.69, 11.27, 11.11, 10.15, 10.78, 10.58, 11.49, 10.94, 11.64, 10.32, 11.63, 10.03, 10.81, 11.83, 10.82, 11.84, 10.79, 10.66, 11.21, 10.24, 11.75, 11.2 ] }

And other 4 similar stuff.

I don't know if there is any way that can trim $volts this kind data int group pipeline. The $limit or $skip operation seems use for whole documents.

My dream result should look like below.

{ "_id" : { "esn" : "b", "vin" : "2" }, "firstTimestamp" : NumberLong("1485852368147"), "volts" : [ 10.81, 11.83, 10.82, 11.84, 10.79, 10.66, 11.21, 10.24, 11.75, 11.2 ], "innerVolts":[...], "temp":[...] }

Upvotes: 0

Views: 1472

Answers (2)

CEDA
CEDA

Reputation: 55

You can use the $slice modifier to trim the array to the lastest N items.

Upvotes: 1

Israel Zinc
Israel Zinc

Reputation: 2769

If you need to trim the results, you can use projection and do something like this:

db.log.aggregate([
         {$sort:{timestamp:-1}},
         {$group:{
                  _id : {esn:"$esn",vin:"$vin"},
                 firstTimestamp:{$first:"$timestamp"},
                 volts:{$addToSet:"$volt"},
                 innerVolts:{$addToSet:"$innerVolt"},
                 temp:{$addToSet:"$temp"}                     
          }},
          { $project: {
               _id:1,
               firstTimestamp:1,
               volts: {$slice : ["$volts",10]},
               innerVolts: {$slice : ["$innerVolts",10]}, 
               temp: {$slice:["$temp",10]}
           }}])

Hope my answer was helpful.

Upvotes: 2

Related Questions