您能做的最好的事情是在文档本身上维护一个“voteCount”。原因很快就会变得显而易见。
您可以在数组中添加或删除成员时保持这一点。假设您正在使用 ObjectId 和 $push 和 $pull 更新运算符来执行此操作。因此,您还 $inc 使用一些查询逻辑来确保您不会重复投票的“用户对象 ID”。假设一个名为“Product”的模型:
Product.update(
{
"_id": ObjectId("53e8675aea39355818ec4ab2"),
"votes": { "$ne": ObjectId("53e87caaca37ffa384e5a931") }, // the user ObjectId
},
{
"$push": { "votes": ObjectId("53e87caaca37ffa384e5a931" }, // same Id
"$inc": { "voteCount": 1 }
},
function(err) {
}
);
并删除:
Product.update(
{
"_id": ObjectId("53e8675aea39355818ec4ab2"),
"votes": ObjectId("53e87caaca37ffa384e5a931"), // the user ObjectId
},
{
"$pull": { "votes": ObjectId("53e87caaca37ffa384e5a931" }, // same Id
"$inc": { "voteCount": -1 }
},
function(err) {
}
);
那么就只需要在字段上进行排序了:
Product.find().sort({ "voteCount": -1 }).limit(1).exec(function(err,doc) {
});
但是如果由于某种原因您认为在文档中保留“voteCount”不合适,那么您需要使用聚合框架手动“投影”它。在您拥有 MongoDB 2.6 或更高版本的情况下,也可以使用 $size 聚合方法:
Product.aggregate(
[
{ "$project": {
"product": 1,
"vote": 1,
"review": 1,
"stars": 1,
"email": 1,
"voteCount": { "$size": "$vote" }
}},
{ "$sort": { "voteCount": -1 } },
{ "$limit": 1 }
],
function(err,result) {
}
);
或者通过阵列上的$unwind 并通过$sum 获取早期版本的计数:
Product.aggregate(
[
{ "$unwind": "$vote"
{ "$group": {
"_id": "$_id",
"product": { "$first": "$product" },
"vote": { "$push": "$vote" },
"review": { "$first": "$review" },
"stars": { "$first": "$stars" },
"email": { "$first": "$email" },
"voteCount": { "$sum": 1 }
}},
{ "$sort": { "voteCount": -1 } },
{ "$limit": 1 }
],
function(err,result) {
}
);
除非您确实需要除数组长度之外的其他计算,否则聚合方法的实现实际上并没有那么大的意义。所以最好把它保存在文档中。