I have a schema in which properties can have respective "override" documents stored in an Array("overrides")
E.g.
`{
foo:'original foo',
overrides: [
{property:'foo', value:'foo override'},
{property:'bar', value:'bar override'},
]
}`
I want to project a field for the override value if it exists, otherwise, the original property.
So something like this
project: { overrideOrOriginal: {$cond: fooOverrideExists ? fooOverrideValue : originalFooValue }
So in this example, I would expect overrideOrOriginal to equal 'foo override' . If - {property:'foo', value:'foo override'} subDoc didn't exist in the overrides array (or if overrides array itself didn't even exist)...then I'd expect overrideOrOriginal = 'original foo'
How can I do this?
I was thinking I'd need $exists in tandem with $cond. But the complication here is that I'm searching for a subDoc in an Array based on a query
Thanks!
CodePudding user response:
$into check "foo" is inoverrides.propertyarray$indexOfArrayto get index of array element inoverrides.propertyarray$arrayElemAtto get element by specific index return from above operator
let fooOverrideExists = "foo";
db.collection.find({},
{
overrideOrOriginal: {
$cond: [
{ $in: [fooOverrideExists, "$overrides.property"] },
{
$arrayElemAt: [
"$overrides.value",
{ $indexOfArray: ["$overrides.property", fooOverrideExists] }
]
},
"$foo"
]
}
})
CodePudding user response:
Query
- find the property , key-value(kv) (it works for all property names)
(assumes your schema with only string value the value of that property) - checks if that it exists in the overrides array
- if it exists, takes the value from the array
- else keeps the original
*checks also cases where override doesnt exists, or its empty array, or property doesn't exist
In case you already know the "foo" use this and ignore the first big part.
db.collection.aggregate([
{
"$set": {
"kv": {
"$arrayElemAt": [
{
"$filter": {
"input": {
"$objectToArray": "$$ROOT"
},
"cond": {
"$eq": [
{
"$type": "$$this.v"
},
"string"
]
}
}
},
0
]
}
}
},
{
"$set": {
"index": {
"$indexOfArray": [
"$overrides.property",
"$kv.k"
]
}
}
},
{
"$project": {
"_id": 0,
"overrideOrOriginal": {
"$cond": [
{
"$or": [
{
"$eq": [
"$index",
-1
]
},
{
"$not": [
"$overrides"
]
}
]
},
"$kv.v",
{
"$arrayElemAt": [
"$overrides.value",
"$index"
]
}
]
}
}
}
])
