12

I have an event object which is fetched from MongoDB via Mongoose plug in. Have done some of the operation in this object and finally I want to save this object in another collection with same structure.

For this I need to delete all properties starts from '_' or '__' like '_id' and '__v'. I have written code like:

console.log(event);
console.log(delete event._id);
console.log(event);

Line 1 and 3 prints same value with _id property. Same thing works fine if I delete some other property like 'code'. here is complete event object:

{ _id: 5a51019b211d740a174a1fba,
  __t: 'EventModel',
  code: '02',
  event: 'testMe',
  source: 'user',
  target: 'cronjob',
  __v: 0,
  params: 
     [ { key: 'Nodics',
         value: 'Framework',
         _id: 5a51019b211d740a174a1fbb } ],
  log: [ 'Published Successfully' ],
  hits: 1,
  type: 'ASYNC',
  state: 'FINISHED',
  testProperty: 'Nodics Framework',
  updatedDate: 2018-01-13T17:04:15.288Z,
  creationDate: 2018-01-13T17:04:15.288Z 
}

Please help me out to understand root cause and how I can deal with this. for me it looks direct or inherited properties issue. but required experts comments.

Himkar Dwivedi
  • 241
  • 3
  • 7

6 Answers6

14

It looks like the reason you can't delete some of those properties is that they have been defined as "non-configurable." However, your approach is sub-optimal because it necessarily mutates its argument. Never, ever, mutate an argument. Ever.

Rather than delete properties from event, you ought to construct a new object that contains only the properties you desire.

  • you can safelist specific properties that you wish to transfer (and save)
  • you can blocklist specific properties that you don't wish to save
  • you can transfer only those properties that live directly on the object, rather than the prototype chain, using Object.getOwnPropertyNames

Libraries like lodash have sugar for doing this kind of thing:

// safelist (using lodash)
var saveableEvent = _.pick(event, ['code', 'event', 'source', 'target', 'params', 'log', 'hits', 'type', 'state', 'testProperty', 'updatedDate', 'creationDate']);

// or blocklist (using lodash)
var saveableEvent = _.omit(event, ['_id', '__t', '__v']);

// only copy object's own properties (without lodash)
var saveableEvent = Object.getOwnPropertyNames(event)
.reduce(function(out, propName) {
    return Object.assign(out, event[propName])
}, {})

// create editable copy of object, then remove undesired props
var saveableEvent = event.toObject();
delete saveableEvent._id;
Tom
  • 8,509
  • 7
  • 49
  • 78
4

Did you try lean() when you query? like find(query).lean()... check this http://blog.sandromartis.com/2016/05/08/mongoose-lean/ This will allow you to do any operation to the object.

Other way could be extending the root object with removing unwanted properties from it. you can use https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

example:

var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
delete copy._id;//or whatever you want
console.lg(copy);//check this doesnt have the _id;

Thanks Hope this helps

1

I recently had a similar problem. I used loadash to cut off the values I didn't need from the array, but had to use .toObject() in the fetched object so I could use it as an argument. Something like:

let resultExample = _.omit(exampleObject.toObject(), ['x', 'y', 'z']);
Pavel Smirnov
  • 4,611
  • 3
  • 18
  • 28
0
use something like this 

 var event= event.toObject();
 delete event._id;
Mahmud
  • 41
  • 3
0

Old question, but I'm throwing my 2-cents into the fray....

I came across this issue and I used Object.entries() + Array.reduce() to solve it. Here's my take:

// define dis-allowed keys and values
const disAllowedKeys = ['_id','__v','password'];
const disAllowedValues = [null, undefined, ''];

// our object, maybe a Mongoose model, or some API response
const someObject = {
  _id: 132456789,
  password: '$1$O3JMY.Tw$AdLnLjQ/5jXF9.MTp3gHv/',
  name: 'John Edward',
  age: 29,
  favoriteFood: null
}; 

// use reduce to create a new object with everything EXCEPT our dis-allowed keys and values!
const withOnlyGoodValues = Object.entries(someObject).reduce((ourNewObject, pair) => {
  const key = pair[0];
  const value = pair[1]; 
  if (
    disAllowedKeys.includes(key) === false &&
    disAllowedValues.includes(value) === false
  ){
    ourNewObject[key] = value; 
  }
  return ourNewObject; 
}, {}); 

// what we get back...
// {
//   name: 'John Edward',
//   age: 29
// }

// do something with the new object!
server.sendToClient(withOnlyGoodValues);

This can be cleaned up more once you understand how it works, especially with some fancy ES6 syntax. I intentionally tried to make it extra-readable, for the sake of the demo.

Read docs on how Object.entries() works: MDN - Object.entries()

Read docs on how Array.reduce() works: MDN - Array.reduce()

TJBlackman
  • 1,895
  • 3
  • 20
  • 46
-2

Thanks for quick help. You first solution works, but has only issue that, properties are hardcoded, though we can make it configurable. Second solution I tried but couldn't gives any effect. Third one is good, but copies hell lot of properties, those we really don't required.

Apart from these I tried following solution and works for now, though its costly for performance but its fine till I don't get one proper:

let savableEvent = JSON.parse(JSON.stringify(event));
delete savableEvent._id;
delete savableEvent.__v;
delete savableEvent.__t;

Will post if I get something better.

Himkar Dwivedi
  • 241
  • 3
  • 7