How to update nested array of documents with Mongoose merging with $set

Viewed 102

i have the following schemas defined in my app:

    const PlanVariantSchema = new mongoose.Schema({
    sku: {
        type: String,
        required: true,
    },

    name: {
        es: {
            type: String,
        },
        en: {
            type: String,
        },
    },

    price: {
        type: Number,
        required: true,
    },

    attributes: [
        {
            key: {
                es: {
                    type: String,
                },
                en: {
                    type: String,
                },
            },

            value: {
                es: {
                    type: String,
                },
                en: {
                    type: String,
                },
            },
        },
    ],
});

const PlanSchema = new mongoose.Schema(
    {
        _id: {
            type: String,
            default: uuid.v4,
        },
        name: {
            es: {
                type: String,
                required: true,
            },
            en: {
                type: String,
                // required: true,
            },
        },


        sku: {
            type: String,
            required: true,
            unique: true,
        },

        variants: [PlanVariantSchema],

        deletionFlag: {
            type: Boolean,
            isRequired: true,
            default: false,
        },
    },
    { collection: "Plan", timestamps: true }
);

AS you can see, some attributes are opened in 2 keys (es, en) as my application needs to support I18n. When i update a Plan, i'm saving all the values again, but merging the fields which support a locale (such as name or description). I'm not having a problem with this, my issue is that i cannot a find a way to update, for example, the "attributes" attribute (sorry for the naming) that is an array inside PlanVariants, which the latter is an array inside Plan.

Searching on the mongo documentation, i've found the positionl $ opreator, but i don't think this solves my issue, because i've read all the examples, and this operator is useful for updating a specific field of all the array items with one value, but i'm trying to update the attributes array with new attirbutes items, merging the fields that have the locale keys (en, es).

Is there any way for doing this deep nested update merging certain fields on the lowest level?

This is how i'm updating the plan attributes at the first level:

public async save(plan: Plan): Promise<void> {
    const planDb = planMapper.toPersistence(plan);
    if (await MongoosePlan.exists({ _id: plan.id.value })) {
        const { name, description, ...planToUpdate } = planDb;
        const nameLocaleKey = `name.${plan.locale}`;
        const descriptionLocaleKey = `description.${plan.l

        await MongoosePlan.updateOne(
            { _id: plan.id.value },
            { ...planToUpdate, $set: { [nameLocaleKey]: name[plan.locale], [descriptionLocaleKey]: description[plan.locale] } }
        );
    } else {
        await MongoosePlan.create(planDb);
    }
}
0 Answers
Related