Използване на 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
ви позволява да трансформирате основния документ с динамични ключове (обозначени със системната променлива $$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
действа като механизъм за филтриране на масива, създаден от $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"
}
}
]
}
Това ще трансформира филтрирания масив от
[
{
"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"
}
}
}
Това ще повиши филтрирания документ с динамичен ключ до най-високо ниво и ще замени всички други полета. Операцията замества всички съществуващи полета във входния документ, включително _id
поле.
По същество това трансформира горния документ
{
"_id" : 1,
"key" : {
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
}
до желания краен резултат
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}