[英]MongoDB Aggregation to conditionally update usernames in all of the collection with large number of documents
我们在 Mongo Atlas 中有一个包含大量文档的userLogin
集合。 如果字段不是小写,我必须编写一个聚合来小写username
名字段。 该集合包含大量文档(超过 500,000 个)。
我编写了以下聚合函数,如果字段有任何不是小写的字符,它会小写该字段。 如果用户名字段中的值与其小写值不相等,我将使用$match
检查,在这种情况下,使用$set
我将字段设置为小写值。
await userLogin.aggregate([
{
'$match': {
'$expr': {
'$ne': [
'$username', {
'$toLower': '$username'
}
]
}
}
}, {
'$set': {
'username': {
'$toLower': '$username'
}
}
}
,
{
$out: 'userLogin',
},
]);
它适用于用户名中包含大写字符的文档。 但是,如果用户名已经是小写,则文档将被删除。 我究竟做错了什么?
编辑:由于用户名上有一个唯一索引,如果集合中已经存在具有小写用户名的文档,则应跳过当前正在处理的文档(用户名变为小写)。
在您的情况下, $match
条件正在过滤掉已经是lowercase
的文档,这是不必要的。 简单地说,这应该足够了:
await userLogin.aggregate([
{
'$set': {
'username': {
'$toLower': '$username'
}
}
}
,
{
$out: 'userLogin',
},
])
这将设置username
,不管它是否有大写字符。
另外$out
完全替换了集合,这就是为什么使用$match
运行时文档似乎被删除的原因。 要么删除$match
,要么使用$merge
阶段而不是$out
。
这是$merge
文档的链接。
它应该是这样的:
await userLogin.aggregate([
{
'$match': {
'$expr': {
'$ne': [
'$username', {
'$toLower': '$username'
}
]
}
}
}, {
'$set': {
'username': {
'$toLower': '$username'
}
}
}
,
{
$merge: {
into: "userLogin",
on: "_id",
whenMatched: "replace"
},
},
]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.