2

This is a question based on MongoDb - remove all fields that are null. The referred post only gives solution that removes null fields at the top level. However, how can I remove the null fields that embedded?

Please note that I have no idea of the possible names of the null fields and their depth, so I think we have to iterate over each field of each document.

This is an example:

{
    "id": 14770467,
    "f1": "a",
    "f2": null,
    "f3": [
        {
            "id": 76946819,
            "f4": null
        }
    ]
}

I'm expecting something like this:

{
    "id": 14770467,
    "f1": "a",
    "f3": [
        {
            "id": 76946819
        }
    ]
}

Thanks.

R. Zhu
  • 415
  • 4
  • 16

2 Answers2

2

try this

const remove = (data) => {
    for (let key in data) {
        const val = data[key];
        if (val == null) {
            delete data[key];
        } else if (Array.isArray(val)) {
            val.forEach((v) => {
                remove(v);
            });
        }
    }
    return data;
}


db.getCollection('Collection').find({}).forEach((data) => {
    data = remove(data);
    db.getCollection('OtherCollection').insert(data);
    //db.getCollection('Collection').save(data); // update same record
    print(data);
})
Rahul Sharma
  • 9,534
  • 1
  • 15
  • 37
  • Wow! That works like a charm! @Rahul Sharma. But could you explain it a little bit? (I'm sorry that I'm pretty ignorant about MongoDB and JavaScript) Is the "=>" symbol from JS? And how to store the query result in a new collection? Many thanks. – R. Zhu Mar 29 '18 at 09:03
  • Yes its a javascript symbol. How are u checking the results? Are u running node.js? – Rahul Raj Mar 29 '18 at 09:08
  • @R.Zhu I have updated answer check. You can perform the javascript operation in MongoDB. – Rahul Sharma Mar 29 '18 at 09:11
  • @RahulSharma I saved your code as a javascript file and executed from mongo shell as `load('test.js')`. A new collection is created & it gives me exact copy of previous collection. – Rahul Raj Mar 29 '18 at 09:16
  • @RahulSharma I'm using the mongo shell and your code works exactly as I expected! Actually i tested `db.newCollection.save(data)` against `db.newCollection.insert(data)`, and found the result are the same. So `save` and `insert` here are both OK? – R. Zhu Mar 29 '18 at 09:25
  • @R.Zhu How are u executing the script from mongo shell? I used `load` and it isnt updating the collection. – Rahul Raj Mar 29 '18 at 09:30
  • @RahulRaj Works for me. – Rahul Sharma Mar 29 '18 at 09:30
  • @R.Zhu If you want to update same record use save if you want in different collection use save/insert. – Rahul Sharma Mar 29 '18 at 09:31
0

Above was not working for me. But was inspiration to seek for more.

This worked (with MongoDB shell version v4.0.5):

const remove= (obj) => {
   Object.keys(obj).forEach(key => {
     if (obj[key] && typeof obj[key] === 'object') removeEmpty(obj[key]);
     else if (obj[key] == null) delete obj[key];
   });
};

db.getCollection('Collection').find({}).forEach((data) => {
  remove(data);
  db.getCollection('OtherCollection').insert(data);
})
clyde
  • 11
  • 2