使用 MongoDB 3.4.4 及更新版本:
db.coll.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": {
"$eq": [
"$$el.v.samekeyA",
"value1"
]
}
}
}
}
} }
])
上述管道将产生最终输出
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
说明
可以分解管道以显示每个操作员的结果。
$objectToArray
$objectToArray 使您能够使用动态键转换根文档
(由系统变量 $$ROOT 表示)到一个数组中,该数组包含原始文档中每个字段/值对的元素。返回数组中的每个元素都是一个包含两个字段 k 和 v 的文档。
在 $project 阶段仅使用操作员运行管道
db.coll.aggregate([
{ "$project": {
"keys": { "$objectToArray": "$$ROOT" }
} }
])
产量
{
"_id" : 1,
"keys" : [
{
"k" : "_id",
"v" : 1
},
{
"k" : "key1",
"v" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
},
{
"k" : "key2",
"v" : {
"samekeyA" : "value3",
"samekeyB" : "value4"
}
},
{
"k" : "key3",
"v" : {
"samekeyA" : "value5",
"samekeyB" : "value6"
}
}
]
}
$filter
$filter 运算符充当由 $objectToArray 运算符生成的数组的过滤机制,通过选择要返回的数组的子集来工作指定的条件
成为您的查询。
考虑以下管道,它返回与条件 { "samekeyA": "value1" } 匹配的键/值对数组
db.coll.aggregate([
{ "$project": {
"keys": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": {
"$eq": [
"$$el.v.samekeyA",
"value1"
]
}
}
}
} }
])
产生
{
"_id" : 1,
"keys" : [
{
"k" : "key1",
"v" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
]
}
$arrayToObject
这将从
转换上面的过滤数组
[
{
"k" : "key1",
"v" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
]
到带有动态键的原始文档
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
所以运行管道
db.coll.aggregate([
{ "$project": {
"key": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": {
"$eq": [
"$$el.v.samekeyA",
"value1"
]
}
}
}
}
} }
])
会产生
{
"_id" : 1,
"key" : {
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
}
$replaceRoot
这会将过滤后的动态密钥文档提升到顶层并替换所有其他字段。该操作将替换输入文档中的所有现有字段,包括_id 字段。
基本上这会改变上述文档
{
"_id" : 1,
"key" : {
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
}
到想要的最终输出
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}