mongodb - 将值从旧字段迁移到 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": {}
}
]
目前此选项有效,但存在一个大问题。事实上,在每个文档中我都重新创建了“interfaces”字段,并且我必须明确指定附加文档的所有字段,否则只会有一个新字段。如果将来文档中出现新字段并且有可能忘记在迁移中指定新字段,这是一个危险的时刻。
我将不胜感激有关如何改进查询的帮助和建议,以便在将数据迁移到新字段时,我不会丢失其余字段。
解决方案
有一个答案。$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": {}
}
]
推荐阅读
- mongodb - Mongodb Aggregation group, count and group
- html - CSS调整按钮大小
- python - How to store 128-d facial encodings in a numpy multidimensional array?
- node.js - 在节点中使用猫鼬实例
- python - 在 python 中为给定的 YouTube 链接创建意图协议链接
- rust - 还有理由使用lazy_static吗?
- reactjs - React Native 密码锁屏创建。使用状态错误
- python - 自定义印度键盘音译:如何
- svg - 如何在刻度线下方正确对齐刻度值/标签
- angular - 如何为内部元素禁用 routerLink