在我的MongoDB集合中,我有帐户列表,每个帐户都有角色,结构格式如下
{
"_id" : "acc1",
"email" : "acc1@email.com",
"password" : "password",
"roles" : [
"ADMIN",
"USER"
],
},
{
"_id" : "acc2",
"email" : "acc2@email.com",
"password" : "password",
"roles" : [
"USER"
],
},
{
"_id" : "acc2",
"email" : "acc2@email.com",
"password" : "password",
"roles" : [
"ADMIN",
"SYSTEM",
"USER",
],
}
现在,我想添加ROLE_
作为前缀的所有角色,那么JSON应该是
{
"_id" : "acc2",
"email" : "acc2@email.com",
"password" : "password",
"roles" : [
"ROLE_ADMIN",
"ROLE_SYSTEM",
"ROLE_USER",
]
}
我不知道如何实现MongoDB脚本来转换整个文档,将前缀附加到像这样的元素。
答案 0 :(得分:4)
您可以使用cursor.forEach()
迭代收集并更新每个文档。它非常简单,但速度很慢,不应该用于大型集合。
db.users.find().forEach(function (doc) {
var newRoles = doc.roles.map(function (value) {
return "ROLE_" + value;
});
db.users.update(
{_id: doc._id},
{$set: {roles: newRoles}}
);
});
使用MongoDB 3.2测量执行时间,收集50k文档,结果如下:
明显的结论是仅在小型集合中使用这种简单的方法,并坚持使用大型集合的批量方法。
答案 1 :(得分:2)
执行此操作的最佳方法是使用.aggregate()
方法,该方法提供对聚合管道的访问。
在你的管道中你只需要一个$project
的阶段,你使用$map
返回连接字符串的数组。当然$concat
运算符连接字符串并返回连接的字符串。
然后,您迭代聚合结果,这是一个游标,并使用"bulk"操作更新您的文档,以实现最高效率。
var bulkOp = db.users.initializeOrderedBulkOp();
var count = 0;
db.users.aggregate([
{ "$project": {
"roles": {
"$map": {
"input": "$roles",
"as": "role",
"in": { "$concat": [ "ROLE_", "$$role" ] }
}
}
}}
]).forEach(function(doc) {
bulkOp.find( { "_id": doc._id } ).updateOne(
{ "$set": { "roles": doc.roles } }
);
count++;
if (count % 300 === 0) {
// Execute per 300 operations and re-init
bulkOp.execute();
bulkOp = db.users.initializeOrderedBulkOp();
}
})
// Clean up queues
if (count > 0)
bulkOp.execute();
MongoDB 3.2 deprecates Bulk()
及其相关方法,并提供.bulkWrite()
方法。
var requests = [];
db.users.aggregate([
{ "$project": {
"roles": {
"$map": {
"input": "$roles",
"as": "role",
"in": { "$concat": [ "ROLE_", "$$role" ] }
}
}
}}
]).forEach( document => {
requests.push(
{ "updateOne":
{
"filter": { "_id": doc._id },
"update": { "$set": { "roles": doc.roles } }
}
}
);
if (requests.length === 1000) {
// Execute per 1000 operations
db.users.bulkWrite(requests);
requests = [];
}
});
db.users.bulkWrite(requests);
您的文档如下所示:
{
"_id" : "acc1",
"email" : "acc1@email.com",
"password" : "password",
"roles" : [
"ROLE_ADMIN",
"ROLE_USER"
]
}
{
"_id" : "acc2",
"email" : "acc2@email.com",
"password" : "password",
"roles" : [
"ROLE_USER"
]
}
{
"_id" : "acc3",
"email" : "acc2@email.com",
"password" : "password",
"roles" : [
"ROLE_ADMIN",
"ROLE_SYSTEM",
"ROLE_USER"
]
}