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:
$in
to check "foo" is inoverrides.property
array$indexOfArray
to get index of array element inoverrides.property
array$arrayElemAt
to 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"
]
}
]
}
}
}
])