Вы в основном хотите $ifNull
.Это "сортировка" как $exists
, но для операторов агрегации, где она возвращает значение по умолчанию, когда выражение поля возвращает null
, что означает "не там":
{ "$project": {
"finalField": {
"$concat": [
{ "$ifNull": [ "$field1", "" ] },
"-",
{ "$ifNull": [ "$field2", "" ] },
"-",
{ "$ifNull": [ "$field3", "" ] }
]
}
}}
Например, с такими данными, как:
{ "field1": "a", "field2": "b", "field3": "c" },
{ "field1": "a", "field2": "b" },
{ "field1": "a", "field3": "c" }
Вы получаете, безо всяких ошибок, конечно:
{ "finalField" : "a-b-c" }
{ "finalField" : "a-b-" }
{ "finalField" : "a--c" }
Если вы хотите что-то более изощренное, то вместо этогодинамически работать с именами, например:
{ "$project": {
"finalField": {
"$reduce": {
"input": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"cond": { "$ne": [ "$$this.k", "_id" ] }
}
},
"initialValue": "",
"in": {
"$cond": {
"if": { "$eq": [ "$$value", "" ] },
"then": { "$concat": [ "$$value", "$$this.v" ] },
"else": { "$concat": [ "$$value", "-", "$$this.v" ] }
}
}
}
}
}}
, которые могут знать о том, какие поля действительно присутствовали, и пытаться только присоединиться к ним:
{ "finalField" : "a-b-c" }
{ "finalField" : "a-b" }
{ "finalField" : "a-c" }
Вы можете даже вручную указатьсписок полей, если вы не хотите, чтобы $objectToArray
поверх документа или вложенного документа:
{ "$project": {
"finalField": {
"$reduce": {
"input": {
"$filter": {
"input": ["$field1", "$field2", "$field3"],
"cond": { "$ne": [ "$$this", null ] }
}
},
"initialValue": "",
"in": {
"$cond": {
"if": { "$eq": [ "$$value", "" ] },
"then": { "$concat": [ "$$value", "$$this" ] },
"else": { "$concat": [ "$$value", "-", "$$this" ] }
}
}
}
}
}}