Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove all fields that are null

Tags:

null

mongodb

How can I remove all fields that are null from all documents of a given collection?


I have a collection of documents such as:

{
    'property1': 'value1',
    'property2': 'value2',
    ...
}

but each document may have a null entry instead of a value entry.

I would like to save disk space by removing all null entries. The existence of the null entries does not contain any information in my case because I know the format of the JSON document a priori.

like image 783
Till Hoffmann Avatar asked Aug 13 '14 13:08

Till Hoffmann


People also ask

How do I delete all NULL rows in SQL?

Use the delete command to delete blank rows in MySQL. delete from yourTableName where yourColumnName=' ' OR yourColumnName IS NULL; The above syntax will delete blank rows as well as NULL row.

How remove NULL values from all columns in SQL?

SELECT column_names FROM table_name WHERE column_name IS NOT NULL; Query: SELECT * FROM Student WHERE Name IS NOT NULL AND Department IS NOT NULL AND Roll_No IS NOT NULL; To exclude the null values from all the columns we used AND operator.

How do you remove NULL objects?

To remove all null values from an object: Use the Object. keys() method to get an array of the object's keys. Use the forEach() method to iterate over the array of keys. Check if each value is equal to null and delete the null values using the delete operator.


2 Answers

// run in mongo shell  

var coll = db.getCollection("collectionName");
var cursor = coll.find();
while (cursor.hasNext()) {
    var doc = cursor.next();
    var keys = {};
    var hasNull = false;
    for ( var x in doc) {
        if (x != "_id" && doc[x] == null) {
            keys[x] = 1;
            hasNull = true;
        }
    }
    if (hasNull) {
        coll.update({_id: doc._id}, {$unset:keys});
    }
}
like image 108
Wizard Avatar answered Oct 20 '22 19:10

Wizard


Starting Mongo 4.2, db.collection.update() can accept an aggregation pipeline, finally allowing the removal of a field based on its value:

// { _id: ObjectId("5d0e8...d2"), property1: "value1", property2: "value2" }
// { _id: ObjectId("5d0e8...d3"), property1: "value1", property2: null, property3: "value3" }
db.collection.update(
  {},
  [{ $replaceWith: {
    $arrayToObject: {
      $filter: {
        input: { $objectToArray: "$$ROOT" },
        as: "item",
        cond: { $ne: ["$$item.v", null] }
      }
    }
  }}],
  { multi: true }
)
// { _id: ObjectId("5d0e8...d2"), property1: "value1", property2: "value2" }
// { _id: ObjectId("5d0e8...d3"), property1: "value1", property3: "value3" }

In details:

  • The first part {} is the match query, filtering which documents to update (in our case all documents).

  • The second part [{ $replaceWith: { ... }] is the update aggregation pipeline (note the squared brackets signifying the use of an aggregation pipeline):

    • With $objectToArray, we first transform the document to an array of key/values such as [{ k: "property1", v: "value1" }, { k: "property2", v: null }, ...].
    • With $filter, we filter this array of key/values by removing items for which v is null.
    • We then transform back the filtered array of key/values to an object using $arrayToObject.
    • Finally, we replace the whole document by the modified one with $replaceWith.
  • Don't forget { multi: true }, otherwise only the first matching document will be updated.

like image 44
Xavier Guihot Avatar answered Oct 20 '22 19:10

Xavier Guihot