使用 $addToSet 时 MongoDB 数组的最大大小
Max size of MongoDB array when using $addToSet
使用:
db.collection('users').update(
{ "_id": user._id},
{ "$addToSet": { "keywords.RFD": keywords } },
function(err, result) {
if (err) {
console.log(
'failed to add keyword "%s" for user: %s', keywords, user.email);
throw err;
}
else {
console.log('Keyword added: ' + keywords );
res.end('{"success" : "Updated Successfully.", "status" : 200}');
}
}
);
我想将关键字的数量限制为 50 个,如果关键字超过 50 个则抛出错误。如果数据库中已经有 50 个,我可以用 MongoDB 查询吗?
告诉你什么。您没有正确阅读文档。所以 keywords
在这里是一个“用词不当”,因为它在这种情况下只能是单数字符串或其他对象。当然不是数组。
但是是的 MongoDB有办法处理这个问题。就像我给出的指针一样,您需要阅读 $each
documentation, along with other modifiers:
db.collection('users').update(
{ "_id": user._id},
{
"$addToSet": {
"keywords.RFD": {
"$each": [keywords],
}
}
)
然后您实际上可以调用一个单独的更新语句 $slice
with a blank call to $each
。有趣的是,它工作得很好。
db.collection('users').update(
{ "_id": user._id},
{
"$push": {
"keywords.RFD": {
"push": {"$each": [] },
},
"$slice": -50
}
)
这里主要的键修饰符是$slice
,这是一种“限制”数组大小的形式。
请注意,您需要 MongoDB 2.6 或更高版本作为服务器版本,这些运算符才能在更新时有效。如果您需要这种交互,这是升级的一个令人信服的理由。
P.S.: 正如我之前所说,您示例中“关键字”的上下文是一个“用词不当”,因为它被认为是一个“标量”值。在 $each
修饰符下,这确实可以是一个数组。因此:
db.collection('users').update(
{ "_id": user._id},
{
"$addToSet": {
"keywords.RFD": {
"$each": { "$each": keywords },
}
}
)
db.collection('users').update(
{ "_id": user._id},
{
"$push": {
"keywords.RFD": {
"push": [],
},
"$slice": -50
}
)
不是原子的。但尽可能接近,尤其是在使用 Bulk API.
时
我认为也许有一种方法可以使用 MongoDB 像封顶数组一样对数组本身添加严格限制,但我认为这是不可能的。我最终只是使用逻辑。
if (user.settings.max_keywords <= result.keywords.RFD.length){
res.end('{"error" : "Too many keywords.", "status" : 401}');
}
const MAX_KEYWORDS = 50;
const maxArrayPath = `keywords.RFD.${MAX_KEYWORDS - 1}`;
db.collection('users').updateOne(
{ _id: user._id,
[maxArrayPath]: { $exists: false }
},
{
$addToSet: {
"keywords.RFD": keywords,
}
}
);
使用:
db.collection('users').update(
{ "_id": user._id},
{ "$addToSet": { "keywords.RFD": keywords } },
function(err, result) {
if (err) {
console.log(
'failed to add keyword "%s" for user: %s', keywords, user.email);
throw err;
}
else {
console.log('Keyword added: ' + keywords );
res.end('{"success" : "Updated Successfully.", "status" : 200}');
}
}
);
我想将关键字的数量限制为 50 个,如果关键字超过 50 个则抛出错误。如果数据库中已经有 50 个,我可以用 MongoDB 查询吗?
告诉你什么。您没有正确阅读文档。所以 keywords
在这里是一个“用词不当”,因为它在这种情况下只能是单数字符串或其他对象。当然不是数组。
但是是的 MongoDB有办法处理这个问题。就像我给出的指针一样,您需要阅读 $each
documentation, along with other modifiers:
db.collection('users').update(
{ "_id": user._id},
{
"$addToSet": {
"keywords.RFD": {
"$each": [keywords],
}
}
)
然后您实际上可以调用一个单独的更新语句 $slice
with a blank call to $each
。有趣的是,它工作得很好。
db.collection('users').update(
{ "_id": user._id},
{
"$push": {
"keywords.RFD": {
"push": {"$each": [] },
},
"$slice": -50
}
)
这里主要的键修饰符是$slice
,这是一种“限制”数组大小的形式。
请注意,您需要 MongoDB 2.6 或更高版本作为服务器版本,这些运算符才能在更新时有效。如果您需要这种交互,这是升级的一个令人信服的理由。
P.S.: 正如我之前所说,您示例中“关键字”的上下文是一个“用词不当”,因为它被认为是一个“标量”值。在 $each
修饰符下,这确实可以是一个数组。因此:
db.collection('users').update(
{ "_id": user._id},
{
"$addToSet": {
"keywords.RFD": {
"$each": { "$each": keywords },
}
}
)
db.collection('users').update(
{ "_id": user._id},
{
"$push": {
"keywords.RFD": {
"push": [],
},
"$slice": -50
}
)
不是原子的。但尽可能接近,尤其是在使用 Bulk API.
时我认为也许有一种方法可以使用 MongoDB 像封顶数组一样对数组本身添加严格限制,但我认为这是不可能的。我最终只是使用逻辑。
if (user.settings.max_keywords <= result.keywords.RFD.length){
res.end('{"error" : "Too many keywords.", "status" : 401}');
}
const MAX_KEYWORDS = 50;
const maxArrayPath = `keywords.RFD.${MAX_KEYWORDS - 1}`;
db.collection('users').updateOne(
{ _id: user._id,
[maxArrayPath]: { $exists: false }
},
{
$addToSet: {
"keywords.RFD": keywords,
}
}
);