What i need to implement in a single operation:
- If document exists:
- check if object exists in nested array:
- yes → update object inside array
- no → insert object into array
- check if object exists in nested array:
- If document doesn’t exist:
- insert a new document
Assume I have a collection with a single document:
[
{
"_id": {
"a": 1,
"b": 2
},
"data": [
{
"id": 1,
"c": {
"d": 1
}
},
{
"id": 2,
"c": {
"d": 2
}
}
]
}
]
Case 1: update object in nested array
Nested object (with id = 1) to be updated:
{
"id": 1,
"c": {
"d": 10
}
}
Expected result:
{
"_id": {
"a": 1,
"b": 2
},
"data": [
{
"id": 1,
"c": {
"d": 10
}
},
{
"id": 2,
"c": {
"d": 2
}
}
]
}
Case 2: insert object into nested array
Object to be inserted:
{
"id": 3,
"c": {
"d": 3
}
}
Expected result:
{
"_id": {
"a": 1,
"b": 2
},
"data": [
{
"id": 1,
"c": {
"d": 1
}
},
{
"id": 2,
"c": {
"d": 2
}
},
{
"id": 3,
"c": {
"d": 3
}
}
]
}
Case 3: Document with _id doesn’t exist → need to insert into collection:
Document to be inserted:
{
"_id": {
"a": 2,
"b": 2
},
"data": [
{
"id": 1,
"c": {
"d": 1
}
}
]
}
Expected result - collection of two documents:
[
{
"_id": {
"a": 1,
"b": 2
},
"data": [
{
"id": 1,
"c": {
"d": 1
}
},
{
"id": 2,
"c": {
"d": 2
}
}
]
},
{
"_id": {
"a": 2,
"b": 2
},
"data": [
{
"id": 1,
"c": {
"d": 1
}
}
]
}
]
I have tried to use updateOne() with aggregation pipeline:
db.collection.updateOne({
"_id": {
"a": 1,
"b": 2
}
},
[
{
$set: {
data: {
$cond: [
{
$in: [
1,
"$data.id"
]
},
{
$map: {
input: "$data",
in: {
$mergeObjects: [
"$this",
{
$cond: [
{
$eq: [
"$this.id",
1
]
},
{
"id": 1,
"c": {
"d": 10
}
},
{}
]
}
]
}
}
},
{
$concatArrays: [
"$data",
[
{
"id": 1,
"c": {
"d": 10
}
}
]
]
}
]
}
}
}
],
{
upsert: true
})
It works fine, but when document doesn’t exist, i get an error:
fail to run update: write exception: write errors: [$in requires an array as a second argument, found: missing]
Сan anybody help? Any help would be appreciate