byrdr
byrdr

Reputation: 5477

mongoose remove empty objects or arrays

I have an object which has fields that are sometimes empty on save. My initial thought was to remove empty fields on pre-save, but for some reason that doesn't seem to be working. The object values are still there after they are saved.

module.exports = function(req, res, next) {
var newRecipe = new Recipe(req.body);

newRecipe.pre('save', function (next) {

  var that = this.data;

  Object.keys(that.data).forEach(function(key) {
    if(that.data.hasOwnProperty(key)){
      if(typeof that.data[key] != 'undefined'){
        if (!that.data[key].length){
          delete that.data[key];
       };
    }
  }
});

  next(); 
});

newRecipe.save(function(err, recipe) {
  if (err) {
    console.log(err);
    res.sendStatus(500);
  } else {
    res.sendStatus(200);
  }
}); 
 };

Here is my incoming object:

  { 
  notes: [],
  isHostessGift: false,
  playbook: {},
  location: {},
  wine: { ingredient: false, pairing: false },
  coupons: [],
  ingredients: [{ item: 'd' }],
  categories: { dishType: ["Beverage"], mainIngredient: ["d"] },
  directions: [{ step: 'd' }],
  serves: 9,
  cookTime: 9,
  prepTime: 8,
  headline: 'ccc' 
}

Is there a better approach to this?

Edit: Working from chridam's answer for some reason inherited properties are passing through the hasOwn Property function.

 var hasOwnProperty = Object.prototype.hasOwnProperty;

function isPropertyEmpty(obj) {
if (obj == null)       return true;
if (obj.length > 0)    return false;
if (obj.length === 0)  return true;
for (var key in obj) {
    if (hasOwnProperty.call(obj, key)){
        console.log(key);
    } 
}
return true;


}



module.exports = function(req, res, next) {
    var newRecipe = new Recipe(req.body);

newRecipe.pre('save', function (next) {

 var doc = this;
  Object.keys(doc).forEach(function(key) {
      if (isPropertyEmpty(doc[key])){
          // console.log(_.omit(doc, doc[key]));
      };
  }); 

 console.log(doc); 


  next(); 
});

Consoling out the doc:

strictMode
selected
shardval
saveError
validationError
adhocPaths
removing
inserting
version
getters
_id
populate
populated
wasPopulated
scope
activePaths
ownerDocument
fullPath
emitter
createdAt
sites
published
featured
data
_id
slug
image
$__original_save
save
$__original_save
save
{ image: 'lol.jpg',
  slug: 'lol',
  _id: 561522878ff1d2f9ae9b4323,
  data: 
   { headline: 'lol',
     prepTime: 22,
     cookTime: 6,
     serves: 8,
     directions: [ [Object] ],
     categories: { mainIngredient: [Object], dishType: [Object] },
     ingredients: [ [Object] ],
     coupons: [],
     wine: { pairing: false, ingredient: false },
     location: {},
     playbook: {},
     isHostessGift: false,
     notes: [] },
  featured: false,
  published: false,
  sites: [ 'HOL' ],
  createdAt: Wed Oct 07 2015 09:47:51 GMT-0400 (EDT) }

Upvotes: 2

Views: 2633

Answers (1)

maxko87
maxko87

Reputation: 2940

I was having a lot of problems with this solution when there were nested schemas with optional Array fields. I solved this by creating a new type:

optional_array = 
  type: Mixed
  validate: 
    validator: (v) ->
      return v instanceof Array
    message: '{VALUE} needs to be an array.'

and then setting all my fields to optional_array instead of Array.

Upvotes: 2

Related Questions