在 Mongodb 子文档数组中有没有办法在每个子文档中添加一个新字段
In Mongodb subdocument array is there any way to add a new field in each subcoument
假设我有这样的文档
{
"_id" : 5,
"rows": [
{ "id" : "aab", "value":100},
{ "id" : "aac", "value":400},
{ "id" : "abc", "value":200},
{ "id" : "xyz", "value":300}
]
}
我需要在每个子文档中添加一个新键 "status" : 1 结果应该类似于
{
"_id" : 5,
"rows": [
{ "id" : "aab", "value":100, "status":1},
{ "id" : "aac", "value":400, "status":1},
{ "id" : "abc", "value":200, "status":1},
{ "id" : "xyz", "value":300, "status":1}
]
}
如何通过单个更新查询来做到这一点?
Mongo positional operator $elemMatch
有问题;
The $ operator can update the first array element that matches multiple query criteria specified with the $elemMatch() operator.
所以在这种情况下使用 mongo 查询你应该只更新特定的匹配条件。如果您在匹配中设置 rows.aac
那么您将在 row.aac
数组中添加 status:1
,检查查询如下:
db.collectionName.update({
"_id": 5,
"rows": {
"$elemMatch": {
"id": "abc"
}
}
}, {
$set: {
"rows.$.status": 1
}
}, true, false) // here you insert new field so upsert true
mongo update 展示了 upsert
和 multi
的工作原理。
但是您仍然想更新所有文档,那么您应该使用一些 programming code
或一些 script
。下面的代码使用 cursor forEach 更新所有数据:
db.collectionName.find().forEach(function(data) {
for (var ii = 0; ii < data.rows.length; ii++) {
db.collectionName.update({
"_id": data._id,
"rows.id": data.rows[ii].id
}, {
"$set": {
"rows.$.status": 1
}
}, true, false);
}
})
如果您的文档大小更大,那么使用 mongo bulk update 的更好方法如下代码显示了如何使用 mongo 批量更新:
var bulk = db.collectionName.initializeOrderedBulkOp();
var counter = 0;
db.collectionName.find().forEach(function(data) {
for (var ii = 0; ii < data.rows.length; ii++) {
var updatedDocument = {
"$set": {}
};
var setStatus = "rows." + ii + ".status";
updatedDocument["$set"][setStatus] = 101;
// queue the update
bulk.find({
"_id": data._id
}).update(updatedDocument);
counter++;
// re-initialize every 1000 update statements
if (counter % 1000 == 0) {
bulk.execute();
bulk = db.collectionName.initializeOrderedBulkOp();
}
}
});
// Add the rest in the queue
if (counter % 1000 != 0)
bulk.execute();
假设我有这样的文档
{
"_id" : 5,
"rows": [
{ "id" : "aab", "value":100},
{ "id" : "aac", "value":400},
{ "id" : "abc", "value":200},
{ "id" : "xyz", "value":300}
]
}
我需要在每个子文档中添加一个新键 "status" : 1 结果应该类似于
{
"_id" : 5,
"rows": [
{ "id" : "aab", "value":100, "status":1},
{ "id" : "aac", "value":400, "status":1},
{ "id" : "abc", "value":200, "status":1},
{ "id" : "xyz", "value":300, "status":1}
]
}
如何通过单个更新查询来做到这一点?
Mongo positional operator $elemMatch
有问题;
The $ operator can update the first array element that matches multiple query criteria specified with the $elemMatch() operator.
所以在这种情况下使用 mongo 查询你应该只更新特定的匹配条件。如果您在匹配中设置 rows.aac
那么您将在 row.aac
数组中添加 status:1
,检查查询如下:
db.collectionName.update({
"_id": 5,
"rows": {
"$elemMatch": {
"id": "abc"
}
}
}, {
$set: {
"rows.$.status": 1
}
}, true, false) // here you insert new field so upsert true
mongo update 展示了 upsert
和 multi
的工作原理。
但是您仍然想更新所有文档,那么您应该使用一些 programming code
或一些 script
。下面的代码使用 cursor forEach 更新所有数据:
db.collectionName.find().forEach(function(data) {
for (var ii = 0; ii < data.rows.length; ii++) {
db.collectionName.update({
"_id": data._id,
"rows.id": data.rows[ii].id
}, {
"$set": {
"rows.$.status": 1
}
}, true, false);
}
})
如果您的文档大小更大,那么使用 mongo bulk update 的更好方法如下代码显示了如何使用 mongo 批量更新:
var bulk = db.collectionName.initializeOrderedBulkOp();
var counter = 0;
db.collectionName.find().forEach(function(data) {
for (var ii = 0; ii < data.rows.length; ii++) {
var updatedDocument = {
"$set": {}
};
var setStatus = "rows." + ii + ".status";
updatedDocument["$set"][setStatus] = 101;
// queue the update
bulk.find({
"_id": data._id
}).update(updatedDocument);
counter++;
// re-initialize every 1000 update statements
if (counter % 1000 == 0) {
bulk.execute();
bulk = db.collectionName.initializeOrderedBulkOp();
}
}
});
// Add the rest in the queue
if (counter % 1000 != 0)
bulk.execute();