Home > Software engineering >  How to update array of an object in mongodb?
How to update array of an object in mongodb?

Time:07-03

Messages.update(
    {_id: docId, "messages.senderId": friendId},
    {
        $set: {"messages.$[elem].read": true}
    },
    {
        multi: true,
        arrayFilters: [{"elem.senderId": friendId}]
    },
    (err, result) => {
        if (err) {
            return res.status(500).json({message: "Something error occured"   err})
        } else {
            return res.status(200).json({message: "Successfully", result})
        }
    }
)

when this command execute I get an error.

Could not find path "messages.0.senderId" in schema" and my schema is

const Schema = new mongoose.Schema({
    conversations: Array,
    messages: Array
})

How can solve this problem?, please, help me.

i follow this solution but not work.

CodePudding user response:

This is a moongoose error as your schema does not specify the complete structure. You can see here that the Mongo update syntax is working as expected.

It seems this is a missing feature for now, As seen in the source code (mongoose v6)

if (schematype == null) {
  if (!strictQuery) {
    return;
  }
  // For now, treat `strictQuery = true` and `strictQuery = 'throw'` as
  // equivalent for casting array filters. `strictQuery = true` doesn't
  // quite work in this context because we never want to silently strip out
  // array filters, even if the path isn't in the schema.
  throw new Error(`Could not find path "${filterPath}" in schema`);
}

The comment acknowledges this bad behaviour, but this is still the logic used even for "mixed type" arrays.

You can either:

  1. Update your Array schema to fully describe the object:
const Schema = new mongoose.Schema({
    conversations: Array,
    messages: [{senderId: String}]
})
  1. Pass the strict: false option in the update, this will also disable other validations which means it's the less preferable approach:
Messages.update(
    {_id: docId, "messages.senderId": friendId},
    {
        $set: {"messages.$[elem].read": true}
    },
    {
        multi: true,
        strict: false,
        arrayFilters: [{"elem.senderId": friendId}]
    },
    (err, result) => {
        if (err) {
            return res.status(500).json({message: "Something error occured"   err})
        } else {
            return res.status(200).json({message: "Successfully", result})
        }
    }
)

CodePudding user response:

This is a moongoose error as your schema does not specify the complete structure. You can see here that the Mongo update syntax is working as expected.

It seems this is a missing feature for now, As seen in the source code (mongoose v6)

if (schematype == null) {
  if (!strictQuery) {
    return;
  }
  // For now, treat `strictQuery = true` and `strictQuery = 'throw'` as
  // equivalent for casting array filters. `strictQuery = true` doesn't
  // quite work in this context because we never want to silently strip out
  // array filters, even if the path isn't in the schema.
  throw new Error(`Could not find path "${filterPath}" in schema`);
}

The comment acknowledges this bad behaviour, but this is still the logic used even for "mixed type" arrays.

You can either:

  1. Update your Array schema to fully describe the object:
const Schema = new mongoose.Schema({
    conversations: Array,
    messages: [{senderId: String, read: Boolean}]
})
  1. Pass the strict: false option in the update, this will also disable other validations which means it's the less preferable approach:
Messages.update(
    {_id: docId, "messages.senderId": friendId},
    {
        $set: {"messages.$[elem].read": true}
    },
    {
        multi: true,
        strict: false,
        arrayFilters: [{"elem.senderId": friendId}]
    },
    (err, result) => {
        if (err) {
            return res.status(500).json({message: "Something error occured"   err})
        } else {
            return res.status(200).json({message: "Successfully", result})
        }
    }
)
  • Related