我从一个帖子收集了以下2个文档。如何仅从"post"中获取键值对对象。匹配条件将使用"post_id"
{
"_id":"1001",
"post":{
"country_name":"India",
"state_name":"Maharashtra",
"city_name":"Mumbai",
"duration":"10",
"country":[
{
"name":"india"
}
],
"site":[
{
"site_no":"101",
"code":"Taj",
"name":"santacruz"
}
]
},
"post_id":"abcd123"
}
{
"_id":"1002",
"post":{
"country_name":"India",
"state_name":"Karnataka",
"city_name":"Bangalore",
"duration":"20",
"country":[
{
"name":"india"
}
],
"site":[
{
"site_no":"201",
"code":"COLES",
"name":"Coles Park"
}
]
},
"post_id":"abcd234"
}
预期结果是:
"abcd123":{
"country_name":"India",
"state_name":"Maharashtra",
"city_name":"Mumbai",
"duration":"10"
}
"abcd234" : {
"country_name":"India",
"state_name":"Karnataka",
"city_name":"Bangalore",
"duration":"20"
}
我可以过滤一个对象,但对于批量和良好的性能,你能帮我解决这个问题吗?
您可以尝试以下聚合查询:
这里的技巧是创建一个具有键k
和v
的对象来定义下一阶段的键和值。
键将为post_id
,值将为具有所需值的对象。
在这种情况下,必须动态创建值,以便您可以:
- 将
$post
对象解析为数组,允许您在其中过滤值。 $filter
的值不使用$type获取数组或对象。- 然后再次使用
$arrayToObject
将数组转换为对象。
最后一步是使用$replaceRoot,这样您就可以得到您想要的输出。
db.collection.aggregate([
{
"$project": {
"k": "$post_id",
"v": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$post" },
"cond": {
"$not": [
{
"$in": [
{ "$type": "$$this.v" },
[ "object", "array" ]
]
}
]
}
}
}
}
}
},
{
"$replaceRoot": {
"newRoot": { "$arrayToObject": [ [ { k: "$k", v: "$v" } ] ] }
}
}
])
例子