0

I want to remove properties _id and __v from Mongo result (which is array with markers) with map, but I always get array with null values in JSON result instead of array with objects without this two properties.

Marker.find().then(result => {
    const markers = result.map(marker => {
        delete marker['_id'];
        delete marker['__v'];
    });
    res.send(JSON.stringify({ markers: markers }));
}).catch(next);

This is how returned JSON looks without mapping:

{
    "markers": [
        {
            "_id": "5a7e266b6d7f6d00147bc269",
            "id": "da27cbf8372aaeb24ce20a21",
            "x": "25",
            "y": "37",
            "timestamp": 2093355239,
            "__v": 0
        },
        {
            "_id": "5a7e2789c61cf90014d67e6b",
            "id": "5580d237f486088499c6d82k",
            "x": "56",
            "y": "29",
            "timestamp": 2138203308,
            "__v": 0
        },
    ]
}

This is how returned JSON looks with mapping:

{
    "markers": [
        null,
        null
    ]
}
1
  • @Andreas Yeah, it is prettified JSON from Postman. Commented Feb 10, 2018 at 13:30

4 Answers 4

2

You need to return something in your map function. The map function returns a new array containing what you return from your map function. If you return nothing it is undefined.

Marker.find().then(result => {
    const markers = result.map(marker => {
        delete marker['_id'];
        delete marker['__v'];
        return marker;
    });
    res.send(JSON.stringify({ markers: markers }));
}).catch(next);
Sign up to request clarification or add additional context in comments.

4 Comments

Doesn't this also mutate the original object (items returned from Marker.find())?
@Caramiriel As far as I know, map function is immutable. For some reason, this properties are still not deleted, although I do get them now.
@Nikola “map function is immutable” — that’s not the point. You’re mutating the result object within map, which is something you should use forEach for, instead. Alternatively, you could map each marker to a new object, not containing _id and __v; this way you don’t mutate result.
@Xufox I understand that. I misunderstood his comment.
1

Instead of deleting (and essentially mutating your result array), you could consider the following

Marker.find().then(result => {
  const markers = result.map(marker => {
    const { ['_id']: _, ['__v']: __, ...rest } = marker;
    return rest;
  });
  res.send(JSON.stringify({ markers: markers }));
}).catch(next);

which would use destructuring to create a copy of the marker, ommitting the 2 properties that you have previously deleted. So _ would contain the value for _id and __ would contain the value for __V, the remaining part of your object would be contained inside the rest variable

7 Comments

Very elegant solution, thanks. For those who don't know; you need to Node 8 to use spread syntax (I got SyntaxError when I tried to use this example because I had 6.9.2). However, this example makes objects full with other things - $__, isNew and $init properties and doesn't solve the problem.
@Nikola It makes a full copy that is true, if you just want specific things then you should rather name the things you do want to receive using destructuring. You are right about Node 8, since this is part of the ES7 destructuring syntax
I don't really understand things now. I thought this should return whole object without _id and __v property, but instead it returns object with $__, isNew and $init (probably meta informations) along with _id and __v too in _doc property. I know how destructuring works, but that would make whole solution (considering the nesting level) so big that it would be easier to just make new object and assign only properties I need to it's properties.
@Nikola that is probably the meta data from your mongo handling, why not get the marker._doc and distruct that one?
you don't understand me. I can do that, but the _doc has literally the same structure as currently returned object. What would I do after I get it? That's like solving the same problem twice.
|
0

Key value pairs can be filtered in the JSON.stringify replacer parameter :

o = {"markers":[{"_id":"5a7e266b6d7f6d00147bc269","id":"da27cbf8372aaeb24ce20a21","x":"25","y":"37","timestamp":2093355239,"__v":0},{"_id":"5a7e2789c61cf90014d67e6b","id":"5580d237f486088499c6d82k","x":"56","y":"29","timestamp":2138203308,"__v":0}]}

j = JSON.stringify(o, (k, v) => k[0] === '_' ? void 0 : v, 2)

console.log(j)

Comments

0

Problem is solved. None of given solutions have worked because the problem was about Mongoose. Data returned by Mongoose is MongooseDocument and is not editable. I just had to add lean() method in query to get the editable result. After that, I used Icepickle's solution.

Marker.find().lean().then(result => {
  const markers = result.map(marker => {
    const { ['_id']: _, ['__v']: __, ...rest } = marker;
    return rest;
  });
  res.send(JSON.stringify({ markers: markers }));
}).catch(next);

2 Comments

Where do you use the lean() in your process workflow (so that other might use it in the future)?
@Icepickle Oops, I forgot to add it in example.

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.