[英]Migrating a value from an old field to a new field inside subdocuments in an array for mongodb
我在 mongo 集合的每個文檔中都有一項任務,將值從一個字段遷移到另一個新字段。
數據最初外觀的示例:
{
"_id" : ObjectId("5ec402eca370d5834f18b762"),
"serial" : "SN12345678",
"hostname" : "router1",
"interfaces" : [
{
"name" : "eth0",
"type" : "sfp",
"connection": "isp"
"ip" : "192.168.1.1/24",
"gateway" : "192.168.1.254",
},
{
"name" : "eth1",
"type" : "copper",
"connection": "switch"
}
],
}
{
"_id" : ObjectId("1vb402hnk370d9520d18b333"),
"serial" : "SN87654321",
"hostname" : "switch1",
"interfaces" : [
{
"name" : "eth0",
"type" : "copper",
"connection": "pc"
},
{
"name" : "eth1",
"type" : "copper",
"connection": "printer"
}
],
}
我需要將值從“connection”字段移動到每個集合文檔中的“conenction_to”字段。 最終結果應如下所示:
{
"_id" : ObjectId("5ec402eca370d5834f18b762"),
"serial" : "SN12345678",
"hostname" : "router1",
"interfaces" : [
{
"name" : "eth0",
"type" : "copper",
"connection_to": {
"device_type": "isp"
}
"ip" : "192.168.1.1/24",
"gateway" : "192.168.1.254",
},
{
"name" : "eth1",
"type" : "copper",
"connection_to": {
"device_type": "switch"
}
}
],
}
{
"_id" : ObjectId("1vb402hnk370d9520d18b333"),
"serial" : "SN87654321",
"hostname" : "switch1",
"interfaces" : [
{
"name" : "eth0",
"type" : "copper",
"connection_to": {
"device_type": "pc"
}
},
{
"name" : "eth1",
"type" : "copper",
"connection_to": {
"device_type": "printer"
}
}
],
}
我有一個用 golang 編寫的微服務與 mongo 數據庫一起工作,遷移機制內部是使用 github.com/golang-migrate/migrate/ 包實現的(JSON 用作該包的請求源)。
我之前對數據庫沒有太多經驗,並且在處理 mongo 數組中的嵌套文檔時遇到了困難。 首先,我嘗試用通常的“更新”和“設置”來解決問題:
[
{
"update": "devices",
"updates": [
{
"q": {"interfaces": {"$exists" : true}},
"u": {
"$set": {
"interfaces.$[].connection_to": {
"device_type": "$connection"
}
}
},
"multi": true
}
]
}
]
...但我無法重用舊“連接”字段中的值。
我閱讀了文檔並發現必須使用聚合來重用字段值的信息。 我收到了這樣的請求:
[
{
"aggregate": "devices",
"pipeline": [
{
"$match" : {
"interfaces" : { "$exists":true }
}
},
{
"$set":{
"interfaces": {
"$map":{
"input": "$interfaces",
"as": "interface",
"in": {
"name": "$$interface.name",
"type": "$$interface.type",
"ip": "$$interface.ip",
"gateway": "$$interface.gateway",
"connection_to": {
"device_type": "$$interface.connection"
}
}
}
}
}
},
{
"$out": "devices"
}
],
"cursor": {}
}
]
目前這個選項有效,但有一個大問題。 實際上,在每個文檔中,我都重新創建了“接口”字段,並且必須明確指定附加文檔的所有字段,否則只會有一個新字段。 如果將來文檔中出現新字段並且有可能忘記在遷移中指定新字段,那么這是一個危險的時刻。
我將非常感謝有關如何改進查詢的幫助和建議,以便在將數據遷移到新字段時不會丟失其余字段。
有一個答案。 $mergeObjects 的使用
[
{
"aggregate": "devices",
"pipeline": [
{
"$match" : {
"interfaces" : { "$exists":true }
}
},
{
"$set":{
"interfaces": {
"$map":{
"input": "$interfaces",
"as": "interface",
"in": {
"$mergeObjects": [
"$$interface",
"connection_to": {
"device_type": "$$interface.connection"
}
]
}
}
}
}
},
{
"$out": "devices"
}
],
"cursor": {}
}
]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.