11

I am using Mongo 3.2.14

I have a mongo collection that looks like this:

{
'_id':...
'field1':...
'field2':...
'field3':...
etc...
}

I want to aggregate this way:

db.collection.aggregate{
                        '$match':{},
                        '$project':{
                                    'field1':1,
                                    'field2':1,
                                    'field3':1,
                                    etc...(all fields)
                                    }
                        }

Is there a way to include all fields in the project without listing each field one by one ? (I have around 30 fields, and growing...)

I have found info on this here:

MongoDB $project: Retain previous pipeline fields

Include all existing fields and add new fields to document

how to not write every field one by one in project

However, I'm using mongo 3.2.14 and I don't need to create a new field, so, I think I cannot use $addFields. But, if I could, can someone show me how to use it?

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
wi3o
  • 1,467
  • 3
  • 17
  • 29
  • 1
    *"I have 30 fields and growing...*" Okay then great that you actually looked at some answers but your question here actually does not tell us anything other than that statement. What is the problem? `$project` works by **A** Including only the fields you explicitly ask for **B** Or by **Excluding** the fields you explicitly tell it to do. You do not actually explain what it is that you are really doing.All I see here is `$match` and `$project`, and no reasoning at all as to either **why** the fields need to be included or excluded or what the rest of the pipeline needs to be. Explain your case – Neil Lunn Aug 15 '17 at 01:59
  • 1
    "Is there a way to include all fields in the project without listing each field one by one ? (I have around 30 fields, and growing...)" My question starts before "(I have around 30 fields, and growing...)" if that helps... – wi3o Aug 15 '17 at 16:23

2 Answers2

20

Basically, if you want all attributes of your documents to be passed to the next pipeline you can skip the $project pipeline. but if you want all the attributes except the "_id" value then you can pass

{ $project: { _id: 0 } }

which will return every value except the _id.

And if by any chance you have embedded lists or nests that you want to flatten, you can use the $unwind pipeline

Avindu Hewa
  • 1,608
  • 1
  • 15
  • 23
  • 1
    Thanks, I didn't know you can skip the $project pipeline altogether. I also noticed that if I do { $project: { _id: 0 } }, then I have to explicitly list all the fields that I want one by one. So, I decided to include the '_id' and delete that field after I put it in a dataframe. – wi3o Aug 15 '17 at 16:21
  • Here if I have more than 20 fields and want to exclude only 2 of them, can I do it the same way? – khush Jan 24 '22 at 07:31
  • Yes, you can just pass the keys you want to exclude with a value of 0 https://docs.mongodb.com/manual/reference/operator/aggregation/project/#std-label-remove-var – Avindu Hewa Feb 01 '22 at 01:32
3

you can use $replaceRoot

db.collection.aggregate{
    "$match": {},
    "$project": {
        "document": "$$ROOT"
    },
    {
        "$replaceRoot": { "newRoot": "$document" }
    }

this way you can get the exact document returned with all the fields in the document...you don't need to add each field one by one in the $project...try using $replaceRoot at the end of the pipeline.

Tom Carrick
  • 6,349
  • 13
  • 54
  • 78