0

I keep running into trouble when working with ObjectIds and lodash. Say I have two arrays of objects I want to use lodash _.unionBy() with:

var arr1 = [
    {
        _id: ObjectId('abc123'),
        old: 'Some property from arr1',
    },
    {
        _id: ObjectId('def456'),
        old: 'Some property from arr1',
    },
];

var arr 2 = [
    {
        _id: ObjectId('abc123'),
        new: 'I want to merge this with object in arr1',
    },
    {
        _id: ObjectId('def456'),
        new: 'I want to merge this with object in arr1',
    },
];

var res = _.unionBy(arr1, arr2, '_id');

Result

console.log(res);
/*
[
    {
        _id: ObjectId('abc123'),
        old: 'Some property from arr1',
    },
    {
        _id: ObjectId('def456'),
        old: 'Some property from arr1',
    },
    {
        _id: ObjectId('abc123'),
        new: 'I want to merge this with object in arr1',
    },
    {
        _id: ObjectId('def456'),
        new: 'I want to merge this with object in arr1',
    },
]
*/

Desired result

[
    {
        _id: ObjectId('abc123'),
        old: 'Some property from arr1',
        new: 'I want to merge this with object in arr1',
    },
    {
        _id: ObjectId('def456'),
        old: 'Some property from arr1',
        new: 'I want to merge this with object in arr1',
    },
]

Since ObjectIds are objects and they are not pointing to the same reference in many cases (e.g. when fetching documents from MongoDB and comparing with local seed for testing), I cannot use '_id' as iteratee.

How do I use lodash with ObjectIDs to achieve desired results?

1
  • I guess you'll need something like _.unionBy(... x => String(x._id)) Commented Mar 16, 2018 at 12:54

3 Answers 3

1

Try this, I removed ObjectId because it does not work in javascript. You can use .toString for string conversion.

var arr1 = [{
        _id: 'abc123',
        old: 'Some property from arr1',
    },
    {
        _id: 'def456',
        old: 'Some property from arr1',
    },
];

var arr2 = [{
        _id: 'abc123',
        new: 'I want to merge this with object in arr1',
    },
    {
        _id: 'def456',
        new: 'I want to merge this with object in arr1',
    },
];


const data = arr2.reduce((obj, ele) => {
    if (!obj[ele._id]) obj[ele._id] = ele.new;
    return obj;
}, {})

arr1 = arr1.map((d) => {
    if (data[d._id]) {
        d.new = data[d._id];
    }
    return d;
})

console.log(arr1);

Sign up to request clarification or add additional context in comments.

Comments

1

You'll have to use _.unionWith that allows you to use a custom comparator. Use the custom comparator to check equality between the two ObjectIds:

_.unionWith(arr1, arr2, (arrVal, othVal) => arrVal._id.equals(othVal._id));

Hope it helps.

1 Comment

Thank you, I did not quite understand how comperators worked. Unfortunately it didn't help though. It seems union is the wrong path here as it only creates an array of unique values. It doesn't merge the objects it seems.
0

This is what ended up solving my problem.

var res = arr1.map(a => {
  return _.assign(a, _.find(arr2, { _id: a._id }));
});

Thanks to Tushar's answer

Comments

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.