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.

2

6 Answers 6

15

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;
Sign up to request clarification or add additional context in comments.

Comments

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 Comment

Amazing. My object is used as read-only, so lean() was a way to go. Thanks
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']);

Comments

0
use something like this 

 var event= event.toObject();
 delete event._id;

Comments

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()

Comments

-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.

1 Comment

You should try the fourth solution in my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.