**I have a mongo document as below. **
{
"metadata": {
"docId": "7b96a"
},
"items": {
"content": "abcd",
"contentWithInfo": "content with additional info"
}
}
I want to project content field based on the condition whether contentWithInfo field is present or not. If contentWithInfo is present, it's value should be projected as content field value and contentWithInfo should be empty. Otherwise content should be projected as is. Is it possible?
I tried the following shell query:
db.collection1.aggregate([
{
"$match": {
"metadata.docId": {
"$in": [
"7b96a"
]
}
}
},
{
"$unwind": "$items"
},
{
"$project": {
"metadata": 1,
"items.content": {
"$cond": {
"if": {
"$eq": [
"$items.contentWithInfo",
null
]
},
"then": "$items.content",
"else": "$items.contentWithInfo"
}
}
}
}
])
If contentWithInfo is present, it is returning the following:
{
"metadata": {
"docId": "7b96a"
},
"items": {
"content": "content with additional info"
}
}
If contentWithInfo is not present, it is returning the following:
{
"metadata": {
"docId": "7b96a"
},
"items": {}
}
whereas I expect it to return
{
"metadata": {
"docId": "7b96a"
},
"items": {
"content": "abcd"
}
}
Approach 1
Instead of checking items.contentWithInfo
is null, check whether the items.contentWithInfo
is missing with $type
operator.
db.collection.aggregate([
{
"$match": {
"metadata.docId": {
"$in": [
"7b96a"
]
}
}
},
{
"$unwind": "$items"
},
{
"$project": {
"metadata": 1,
"items.content": {
"$cond": {
"if": {
"$eq": [
{
$type: "$items.contentWithInfo"
},
"missing"
]
},
"then": "$items.content",
"else": "$items.contentWithInfo"
}
}
}
}
])
Demo Approach 1 @ Mongo Playground
Another approach, if you want items.content
as default value if items.contentWithInfo
is missing or null, you can use $ifNull
operator.
db.collection.aggregate([
{
"$match": {
"metadata.docId": {
"$in": [
"7b96a"
]
}
}
},
{
"$unwind": "$items"
},
{
"$project": {
"metadata": 1,
"items.content": {
$ifNull: [
"$items.contentWithInfo",
"$items.content"
]
}
}
}
])