我有这样的数据结构:
我们有一些centers
。 center
有一些switches
。 switch
有一些ports
。
{
"_id" : ObjectId("561ad881755a021904c00fb5"),
"Name" : "center1",
"Switches" : [
{
"Ports" : [
{
"PortNumber" : 2,
"Status" : "Empty"
},
{
"PortNumber" : 5,
"Status" : "Used"
},
{
"PortNumber" : 7,
"Status" : "Used"
}
]
}
]
}
我想要的只是编写一个更新查询,将其Status
为5的端口的PortNumber
更改为"清空"。
当我用这个查询知道端口的数组索引(这里数组索引是1)时,我可以更新它:
db.colection.update(
// query
{
_id: ObjectId("561ad881755a021904c00fb5")
},
// update
{
$set : { "Switches.0.Ports.1.Status" : "Empty" }
}
);
但我不知道该端口的数组索引 谢谢你的帮助。
答案 0 :(得分:5)
您通常会使用位置运算符$
执行此操作,如此问题的答案中所述:
Update field in exact element array in MongoDB
不幸的是,现在位置运算符只支持一个深度匹配的数组级别。
对于您想要的行为,有一个JIRA票证:https://jira.mongodb.org/browse/SERVER-831
如果您可以将Switches
改为对象,则可以执行以下操作:
db.colection.update(
{
_id: ObjectId("561ad881755a021904c00fb5"),
"Switch.Ports.PortNumber": 5
},
{
$set: {
"Switch.Ports.$.Status": "Empty"
}
}
)
答案 1 :(得分:1)
由于您不知道端口的数组索引,我建议您动态创建 delete old records
条件,即可以帮助您获取索引的内容对于对象,然后相应地进行修改,然后考虑使用 MapReduce 。
目前,使用聚合框架似乎无法做到这一点。有一个未解决的开放 JIRA issue 与之相关联。但是, MapReduce 可以解决方法。 MapReduce的基本思想是它使用JavaScript作为其查询语言,但这往往比聚合框架慢得多,不应该用于实时数据分析。
在MapReduce操作中,您需要定义几个步骤,即映射步骤(将操作映射到集合中的每个文档,操作可以不执行任何操作或使用键和投影值发出一些对象)和减少步骤(采用发射值列表并将其减少为单个元素)。
对于地图步骤,理想情况下,您希望获取集合中的每个文档,每个$set
和Switches
数组字段的索引以及包含Ports
个键的另一个键
您的简化步骤将是一个函数(无效),简单定义为$set
MapReduce操作的最后一步将创建一个单独的集合开关,其中包含发出的Switches数组对象以及具有var reduce = function() {};
条件的字段。在原始集合上运行MapReduce操作时,可以定期更新此集合。
总而言之,这个MapReduce方法看起来像:
$set
从MapReduce操作中查询输出集var map = function(){
for(var i = 0; i < this.Switches.length; i++){
for(var j = 0; j < this.Switches[i].Ports.length; j++){
emit(
{
"_id": this._id,
"switch_index": i,
"port_index": j
},
{
"index": j,
"Switches": this.Switches[i],
"Port": this.Switches[i].Ports[j],
"update": {
"PortNumber": "Switches." + i.toString() + ".Ports." + j.toString() + ".PortNumber",
"Status": "Switches." + i.toString() + ".Ports." + j.toString() + ".Status"
}
}
);
}
}
};
var reduce = function(){};
db.centers.mapReduce(
map,
reduce,
{
"out": {
"replace": "switches"
}
}
);
通常会给你结果:
Switches
示例输出:
db.switches.findOne()
然后,您可以使用{
"_id" : {
"_id" : ObjectId("561ad881755a021904c00fb5"),
"switch_index" : 0,
"port_index" : 1
},
"value" : {
"index" : 1,
"Switches" : {
"Ports" : [
{
"PortNumber" : 2,
"Status" : "Empty"
},
{
"PortNumber" : 5,
"Status" : "Used"
},
{
"PortNumber" : 7,
"Status" : "Used"
}
]
},
"Port" : {
"PortNumber" : 5,
"Status" : "Used"
},
"update" : {
"PortNumber" : "Switches.0.Ports.1.PortNumber",
"Status" : "Switches.0.Ports.1.Status"
}
}
}
方法中的光标迭代并相应地更新您的集合:
db.switches.find()