假设我有db as;
{ name: "alex" , id: "1"}
我想要更新集合。我想加上“先生”到name字段中的值。
{ name: "Mr.alex" , id: "1"}
我该怎么做?我应该写2个查询作为;
db.collection("user").find({id : "1"}).toArray(function(err, result){
var name = result[0].name;
db.collection("user").updateOne({id : "1"}, {name: "Mr." + name},function(err, result){
})
})
在mongodb中,没有更好的方法可以做x = x+1
吗?
答案 0 :(得分:0)
AFAIK会有两个查询,更新运营商不会获取任何字段的值并需要提供值。
但是,如果您需要为所有文档或大量文档执行此操作,则可以编写脚本并使用游标forEach并为每个文档更改名称并通过传递参数user来调用db.user.save()对象
底线保持不变。
答案 1 :(得分:0)
尝试以下:
var cursor = db.users.find({});
while (cursor.hasNext()) {
var user = cursor.next();
user.name = "Mr." + user.name;
user.save();
}
无法使用一个查询。您必须遍历文档并使用更新的结果保存它们。
答案 2 :(得分:0)
目前无法在同一查询中引用检索到的文档,这样您就可以在同一操作中查找和更新文档。
因此,您必须进行多次查询才能完成您的目标:
/*
* Single Document
*/
// I'm assuming the id field is unique and can only return one document
var doc = db.collection('user').findOne({ id: '1' });
try {
db.collection('user').updateOne({ id: '1' }, { $set: { name: 'Mr. ' + doc.name }});
} catch (e) {
print(e);
}
如果要处理多个更新操作,可以使用Bulk()
操作构建器来执行此操作:
/*
* Multiple Documents
*/
var bulk = db.collection('user').initializeUnorderedBulkOp();
// .forEach is synchronous in MongoDB, as it performs I/O operations
var users = db.collection('user').find({ id: { $gt: 1 } }).forEach(function(user) {
bulk.find({ id: user.id }).update({ $set: { name: 'Mr. ' + user.name }});
});
bulk.execute();
答案 3 :(得分:0)
使用现有字段更新集合的关键是遍历从 find().toarray()
光标方法返回的数组,并使用 Bulk API
更新您的集合,允许您在单个请求中(作为批处理)发送许多更新操作。
让我们通过一些例子看看这支笔是怎样的:
a)对于MongoDB服务器版本3.2及以上
db.collection("user").find({id : "1"}).toArray(function(err, result){
var operations = [];
result.forEach(function(doc){
operations.push({
"updateOne": {
"filter": {
"_id": doc._id,
"name": doc.name
},
"update": {
"$set": { "name": "Mr." + doc.name }
}
}
});
// Send once in 500 requests only
if (operations.length % 500 === 0 ) {
db.collection("user").bulkWrite(operations, function(err, r) {
// do something with result
}
operations = [];
}
});
// Clear remaining queue
if (operations.length > 0) {
db.collection("user").bulkWrite(operations, function(err, r) {
// do something with result
}
}
})
在上文中,您初始化了您的操作数组,该数组将由Bulk API的 bulkWrite()
函数使用并保存更新操作。
然后迭代 find().toarray()
游标函数的结果,以使用更新对象创建操作数组。这些业务仅限于500批次。
选择低于默认批次限制1000的值的原因通常是受控制的选择。正如那里的文档所述,默认情况下MongoDB将发送到s erver in batches of 1000 operations at a time at maximum并且无法保证确保这些默认的1000个操作请求实际适合16MB BSON limit。
所以你仍然需要在" safe"并且施加较小的批量大小,您只能有效地管理它,以便在发送到服务器时总数小于数据限制。
a)如果使用MongoDB v3.0或更低版本:
// Get the collection
var col = db.collection('user');
// Initialize the unordered Batch
var batch = col.initializeUnorderedBulkOp();
// Initialize counter
var counter = 0;
col.find({id : "1"}).toArray(function(err, result){
result.forEach(function(doc) {
batch.find({
"_id": doc._id,
"name": doc.name
}).updateOne({
"$set": { "name": "Mr. " + doc.name }
});
counter++;
if (counter % 500 === 0) {
batch.execute(function(err, r) {
// do something with result
});
// Re-initialize batch
batch = col.initializeOrderedBulkOp();
}
});
if (counter % 1000 != 0 ){
batch.execute(function(err, r) {
// do something with result
});
}
});