Is there anyway i can update only the matching element of the array sub-document with the data from the fields in the local document??
So, This is the schema i am working with.
{
"history": [{ fieldA: Date, fieldB: Number, fieldC: ObjectId }],
"current": {
"fieldD": { type: ObjectId },
"fieldE": { type: Number },
}
}
I am trying to push a new entry to history such that the new entry is
new_entry = { fieldA: new Date, fieldB: current.fieldE, fieldC: current.fieldD }
and if before the document was
{
"history": [
{ fieldA: ISODate("2024-02-18"), fieldB: 6, fieldC: ObjectID("old_id") },
{ fieldA: ISODate("2024-02-25"), fieldB: 6, fieldC: ObjectID("old_id_2") },
{ fieldA: ISODate("2024-03-03"), fieldB: 6, fieldC: ObjectID("old_id_3") }
],
"current": {
"fieldD": ObjectId("new_id"),
"fieldE": 8,
}
}
then after the operations
{
"history": [
{ fieldA: ISODate("2024-02-18"), fieldB: 6, fieldC: ObjectID("old_id") },
{ fieldA: ISODate("2024-02-25"), fieldB: 6, fieldC: ObjectID("old_id_2") },
{ fieldA: ISODate("2024-03-03"), fieldB: 6, fieldC: ObjectID("old_id_3") },
{ fieldA: ISODate("2024-03-11"), fieldB: 8, fieldC: ObjectId("new_id") }
],
"current": {
"fieldD": ObjectId("new_id"),
"fieldE": 8,
}
}
I have been using $concatArrays
but the query is taking around 12minutes to run each time. I was trying to reduce this by using $push
and $set
aggregation like so
let new_date= new Date()
db.collection.updateMany({ "current.fieldD": { $gte: 10, $lte: 23 } }, { $push: { "history": { $each: [{ fieldA: new_date}], $slice: -10 } } });
db.collection.updateMany({ "current.fieldD": { $gte: 10, $lte: 23 } }, [
{ $project: { history: { $filter: { input: "$history", as: "history", cond: { $eq: ["$$history.fieldA", new_date] } } }, "current.fieldD": 1, "current.fieldE": 1 }},
{ $set: { "history.fieldC": "$current.fieldD", "history.fieldB": "$current.fieldE" } }
]
But this seems to set the history for all matching documents as an array of just one object element resulting in a document like
{
"history": [
{ fieldA: ISODate("2024-03-11"), fieldB: 8, fieldC: ObjectId("new_id") }
],
"current": {
"fieldD": ObjectId("new_id"),
"fieldE": 8,
}
}
Is there anyway to update only the matching subdocument with the data from the root document?