Search code examples
mongodbmongoose

Update part of nested array of objects in a parent object using mongoose findByIdAndUpdate


This is a part of a mongoose model

const mandateSchema = new mongoose.Schema({
    _id: {
        type: String,
        required: true,
    },
    customer: {
        type: String,
        required: true,
        index: true
    },
    tariffs: {
        gas: {
            product_name: {
                type: String
            },
            code: {
                type: String
            },
            default_coefficients: {
                type: Boolean,
                default: true
            },
            assigned_eans: [{
                eanID: {
                    type: String,
                    ref: Ean,
                },
                status: {
                    type: String,
                    required: false
                },
                start_date: {
                    type: Number,
                },
                end_date: {
                    type: Number,
                },
                segment: {
                    type: String,
                    enum: ['b2c', 'soho', 'b2b', 'corporate', 'industry', 'direction']
                },
                stop_reason: {
                    type: String
                },
                stop_note: {
                    type: String
                },
            }]
        },
        electricity: {
            product_name: {
                type: String
            },
            code: {
                type: String
            },
            default_coefficients: {
                type: Boolean,
                default: true
            },
            assigned_eans: [{
                eanID: {
                    type: String,
                    ref: Ean,
                },
                start_date: {
                    type: Number,
                },
                end_date: {
                    type: Number,
                },
                segment: {
                    type: String,
                    enum: ['b2c', 'soho', 'b2b', 'corporate', 'industry', 'direction']
                },
                stop_reason: {
                    type: String
                },
                stop_note: {
                    type: String
                },
            }]
        }
    },
    start_date: {
        type: mongoose.Schema.Types.Mixed,
        required: false
    },
    end_date: {
        type: mongoose.Schema.Types.Mixed,
        required: false
    },
    end_from_ip: {
        type: String,
        required: false
    },
    stop_reason: {
        type: String,
        required: false
    },
    stop_reason_description: {
        type: String,
        required: false
    },
    sign_date: {
        type: Number,
        required: false
    },
    sign_token: {
        type: String,
        required: false
    },
    sign_from_ip: {
        type: String,
        required: false
    }
});

Based on a given _id and eanID I'm looking for a way to update the object which matches the eanID with a new status, end_date, stop_reason and optional a stop_note without losing the already filled in start_date and eanID.

The start was pretty easy EnergyMandate.findByIdAndUpdate(energyMandateId. But for the update part I don't know how I can find the matching object. I have checked other solutions on Stackoverflow but in my example there is first the split between tariffs.gas and tariffs.electricity and then the search for a matching eanID.


Solution

  • You can use array filters like this:

    EnergyMandate.findByIdAndUpdate(energyMandateId,
    {
      $set: {
        "tariffs.gas.assigned_eans.$[elem].status": yourNewStatus,
        "tariffs.gas.assigned_eans.$[elem].end_date": yourNewEndDate,
        "tariffs.gas.assigned_eans.$[elem].stop_reason": yourNewStopReason,
        "tariffs.gas.assigned_eans.$[elem].stop_note": yourNewStopNote
      }
    },
    {
      arrayFilters: [
        {
          "elem.eanID": yourEanId
        }
      ]
    })
    

    Example here