How to hide _id from Aggregation?
Asked Answered
K

4

42

I've this query:

produits = yield motor.Op(db.users.aggregate, [{"$unwind":"$pup"},{"$match":{"pup.spec.np":nomp}}, {"$group":{"_id":"$pup.spec.id","pup":{"$push":"$pup"}}}])

which gives me this result:

print produits

{u'ok': 1.0, u'result': [{u'_id': None, u'pup': [{u'avt': {u'fto': ..all the results}}]}]}

so I can do:

prod = produits["result"]

[{u'_id': None, u'pup': [{u'avt': {u'fto': ..all the results}}]}]

but how can I hide "_id" so that I can only get:

[{u'pup': [{u'avt': {u'fto': ..all the results}}]}]

in a normal query I would simply add something like {"_id":0} but here it doesn't work.

Ketchup answered 2/4, 2013 at 23:44 Comment(0)
O
82

From mongodb docs

You can $project the results to exclude the _id - is this what you mean?

http://docs.mongodb.org/manual/reference/aggregation/#pipeline

Note The _id field is always included by default. You may explicitly exclude _id as follows:

db.article.aggregate(
    { $project : {
        _id : 0 ,
        title : 1 ,
        author : 1
    }}
);

From you're example, the first operation in the pipeline would be to exclude the _id and include the other attribs.

Oulu answered 2/4, 2013 at 23:57 Comment(5)
so i must add $project operator ?Ketchup
adding it at the end giveme an error, how do it put it [{"$unwind":"$pup"},{"$match":{"pup.spec.np":nomp}}, {"$group":{"_id":"$pup.spec.id","pup":{"$push":"$pup"}}}, {"$project":{"_id":0}}]Ketchup
Looking at your command, it looks like what you're grouping by is null. I'm not familiar with syntax, but if you're just wanting to eliminate the _id from output, put {$project : {_id:0, pup:1}} as last op on pipelineOulu
that worked, placed at the last: yield motor.Op(db.users.aggregate, [{"$unwind":"$pup"},{"$match":{"pup.spec.np":nomp}}, {"$group":{"_id":"$pup.spec.id","pup":{"$push":"$pup"}}}, {"$project" : {"_id":0, "pup":1}}])Ketchup
can we hide non id fields?Redbud
J
11

Starting Mongo 4.2, the $unset aggregation operator can be used as an alternative syntax for $project when used to only drop fields:

// { _id: "1sd", pup: [{ avt: { fto: "whatever"} }] }
// { _id: "d3r", pup: [{ avt: { fto: "whatever else"} }] }
db.collection.aggregate({ $unset: ["_id"] })
// { pup: [{ avt: { fto: "whatever" } } ] }
// { pup: [{ avt: { fto: "whatever else" } } ] }
Johm answered 9/6, 2019 at 16:32 Comment(0)
S
2

I'm not familiar with motor, but you ought to be able to delete the property from the results dict directly.

>>> produits = {u'ok': 1.0, u'result': [{u'_id': None, u'pup': [{u'avt': {u'fto': 'whatever'}}]}]}
>>> prod = produits['result'] 
>>> del prod[0]['_id']
>>> print prod
[{u'pup': [{u'avt': {u'fto': 'whatever'}}]}]
Septuagenarian answered 2/4, 2013 at 23:54 Comment(1)
thank you, yes i can do it using python using indexes, but it get complicated when there is more than one results, so i must iterate twice, for results (dictionary), and for lists indexes BTW: motor works the same way as pymongo, except it uses callbacks because it makes non blocking callsKetchup
S
-2

This is not exaclty a mongoWay of doing it, but you can use this factory to generate an object that includes all but _id

/**
 * Factory that returns a $project object that excludes the _id property https://docs.mongodb.com/v3.0/reference/operator/aggregation/project/ 
 * @params {String} variable list of properties to be included  
 * @return {Object} $project object including all the properties but _id
 */
function includeFactory(/* properties */){
    var included = { "_id": 0 };
    Array.prototype.slice.call(arguments).forEach(function(include){
        included[include] = true
    })

    return { "$project": included }
}

Then use it like this:

cities.aggregate(
{ "$group": { "_id": null, "max": { "$max": "$age" }, "min": { "$min": "$age" }, "average": { "$avg": "$age" }, "total": { "$sum": "$count" } } },
        includeFactory('max','min','average','total') 
)
Settle answered 11/5, 2016 at 16:58 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.