我目前正試圖使用MongoDB腳本來解決一個問題。讓我試著解釋一下我想要實作的目標。 給定一個MongoDB檔案,我應該能夠在檔案中生成一個鍵的陣列,即使該檔案有嵌套的檔案,也應該使用點運算子顯示在陣列中。我使用JS成功地做到了這一點。
function getDeepKeys(obj) {
var keys = [] 。
const idRegex = new RegExp('_id.*') 。
for (var key in obj) {
if (! (idRegex.test(key)) { //從最終的key陣列中排除id欄位。
keys.push(key)。
if (typeof obj[key] === "object" ) {
var subkeys = getDeepKeys(obj[key])。
keys = keys.concat(subkeys.map(function (subkey) {
return key "。" subkey。
}));
}
}
}
return keys;
}
如果我給出下面的輸入樣本:
{
"_id"/span>: {
"$oid": "613714789a01802b620c2379"
},
"name": "實體2"。
"地址"。"2號公路"。
"documentType": "詳細資訊"。
"personalDetails": {
"gender": "男性"。
"年齡": 23,
"position": null。
}
}
我得到的輸出結果如下:
[
'name'。
'address',
'documentType',
'personalDetails'。
'personalDetails.gender'。
'personalDetails.age'。
'personalDetails.position'
我能否在MongoDB腳本中實作同樣的功能。到目前為止,我已經找到了一個聚合函式,它只回傳頂層的鍵,而不能回傳內部檔案的鍵:
我已經找到了一個聚合函式,它只回傳頂層的鍵,而不能回傳內部檔案的鍵。
db.customers.aggregate( [
{ "$project"/span>: {
"hashhmaps"/span>: { "$objectToArray"/span>: "$ROOT" }
} },
{ "$project": {
"field": "$hashmaps.k"。
} },
{ "$group": {
"_id": null,
"field": { "$addToSet": "$fields" }
} },
{ "$project": {
"keys": {
"$setDifference": [
{
"$reduce": {
"input": "$fields",
"initialValue": [],
"in": { "$setUnion" : ["$value", "$this"] }
}
},
["_id"] ?
]
}
}
}
]).toArray()[0]["keys"] 。
它的回報是:
[
"address"。
"documentType",
"name",
"personalDetails"。
]
其中缺少內部檔案的鍵。如果有任何幫助,我們將不勝感激。這是我使用JS解決的一個大問題的一部分,但是需要使用MongoDB腳本來解決。我的JS解決方案是這里
我使用的是Atlas的免費層,因此不能使用map-reduce等函式。
謝謝你。
uj5u.com熱心網友回復:
可能的,是的。
漂亮,不漂亮。
Aggregation in English
MongoDB中的聚合并沒有像回圈或遞回這樣的結構。
對于直接嵌套在頂層檔案中的檔案,你可以過濾掉任何非物件,預置頂層欄位名,并合并欄位串列:
db.collection.aggregate( [
{$project: {data: {$objectToArray: "$ROOT"}}。
{$addFields: {
fields: "$data.k"。
data: {
$map: {
input: {$filter: {
input: "$data"/span>,
cond: {$eq: ["object", {$type: "$this.v"}]}。
}},
in: {
v: {
$map: {
input: {$objectToArray: "$this.v"}。
as: "sub",
in: {
k: {$concat: ["$this.k","。","$sub.k"]},
v: "$sub.v"], v: "$sub.v"
}
}
}
}
}
}
}},
{$addFields: {
data: {$reduce: {
input: "$data"/span>,
initialValue: [],
in: {$concatArrays: ["$value"/span>, "$this.v"]}}
}}
}},
{$project: {
fields: {$concatArrays: ["$fields"/span>,"$data.k"/span>]}。
}}
])
那么如果你想深入2層,你需要重復中間的階段,就像:
如果你想深入2層,你需要重復中間的階段。
db.collection.aggregate( [
{$project: {data: {$objectToArray: "$ROOT"}}。
{$addFields: {
fields: "$data.k"。
data: {
$map: {
input: {$filter: {
input: "$data"/span>,
cond: {$eq: ["object", {$type: "$this.v"}]}。
}},
in: {
v: {
$map: {
input: {$objectToArray: "$this.v"}。
as: "sub",
in: {
k: {$concat: ["$this.k","。","$sub.k"]},
v: "$sub.v"], v: "$sub.v"
}
}
}
}
}
}
}},
{$addFields: {
data: {$reduce: {
input: "$data"/span>,
initialValue: [],
in: {$concatArrays: ["$value"/span>, "$this.v"]}}
}}
}},
{$addFields: {
fields: {$concatArrays: ["$fields"/span>,"$data.k"/span>]}。
data: {
$map: {
input: {$filter: {
input: "$data"/span>,
cond: {$eq: ["object", {$type: "$this.v"}]}。
}},
in: {
v: {
$map: {
input: {$objectToArray: "$this.v"}。
as: "sub",
in: {
k: {$concat: ["$this.k","。","$sub.k"]},
v: "$sub.v"], v: "$sub.v"
}
}
}
}
}
}
}},
{$addFields: {
data: {$reduce: {
input: "$data"/span>,
initialValue: [],
in: {$concatArrays: ["$value"/span>, "$this.v"]}}
}}
}},
{$project: {
fields: {$concatArrays: ["$fields"/span>,"$data.k"]}}。
}}
])
雖然這在某種程度上是功能性的(Playground),但這只適用于直接嵌入的檔案(而不是檔案的陣列),而且對于你想要處理的每一級嵌套都必須重復這兩個階段。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/319828.html
標籤:
