I would like to insert or update an object in an array, but I dont know how to do it.
My Schema:
const TelemetrySchema = new mongoose.Schema({
Client: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Client',
},
MQTT_FIELD: [
{
_id: false,
Index:
{
type: Number,
required: true,
unique: true,
},
Name: {
type: String,
trim: true,
required: true,
unique: true,
},
},
],
});
I would like to update MQTT_FIELD in my TelemetrySchema:
First, search for Client in Telemetry, insert in MQTT_FIELD, if not exist:
Index = 1, Name = 'K1'
Second, serach for Client in Telemetry, update if not exist
Index = 1, Name = 'K-1'
What did I so far:
const telemetry = await Telemetry.findOneAndUpdate(
{
MQTT_CLIENT: req.body.Client,
'MQTT_FIELD.Index': { $ne: req.body.Field.Index },
},
{
$addToSet: {
MQTT_FIELD: {
Index: req.body.Field.Index,
Name: req.body.Field.Name,
},
},
},
{
upsert: true,
new: true,
omitUndefined: true,
},
).exec();
Inserting in an empty Array MQTT_FIELD works well, but updating is my problem.
I am getting the following error:
duplicate key error collection: mycollection.telemetries index: MQTT_FIELD.Index_1 dup key: { MQTT_FIELD.Index: 1 }
And here is my request body:
{
"Client": "stackoverflow",
"Field":
{
"Index": 1,
"Name": "S1"
}
}
Thanks in advance.
CodePudding user response:
You will have to use the aggregation-pipeline form of update in MongoDb. Something like this:
db.collection.update({
"client": "stackoverflow"
},
[
{
"$set": {
"MQTT_FIELD": {
"$cond": {
"if": {
"$eq": [
{
"$size": {
"$filter": {
"input": "$MQTT_FIELD",
"as": "elem",
"cond": {
"$eq": [
"$$elem.index",
2 <--- Substitute the index from your request body here
]
}
}
}
},
0
]
},
"then": {
"$concatArrays": [
"$MQTT_FIELD",
[
{
name: "S1", <--- Substitute the name from your request body here
index: 1 <--- Substitute the index from your request body here
}
]
]
},
"else": {
"$map": {
"input": "$MQTT_FIELD",
"as": "elem",
"in": {
"$setField": {
"field": "name",
"input": "$$elem",
"value": "S1" <-- substitute the name from your request body here.
}
}
}
}
}
}
}
}
])
Note you can use either update
OR findOneAndUpdate
, any function will work.
Here's the playground link.