我的查询如下:
function getPage(page) {
return db.messages.aggregate(
{
'$group': {
_id: "$subjectID"
}
},
{ '$skip': page * 20 },
{ '$limit' : 20 });
}
假设我知道subjectID
出现在该集合的某个地方。我想要做的是写点:
function pageOf(subjectID) {
return Math.floor(db.messages.aggregate(
{
'$group': {
_id: "$subjectID"
}
}).indexOf({__id: subjectID}) / 20);
}
除了我不知道如何编写该查询的indexOf
部分。我想知道mongodb是否可能有某种“接受”或“接受”查询,然后你可以这样做,然后计算项目数。
答案 0 :(得分:4)
如果您的subjectID
是(或可以更改为)单调递增的值(例如,MongoDB默认的ObjectID),您可以使用正常find()
进行适当排序的直接选项,跳过和限制。在这种情况下,您可以查找主题为$gte
(greater than or equal to) subjectID
的文档
var page = 1;
var subjectID = ObjectId("515535a0760fe8735f5f6897");
db.users.find(
{ _id: { $gte : subjectID } }
).sort({'_id':1}).skip(page*20).limit(20)
与MongoDb 2.4一样,聚合框架中没有此类功能可根据结果管道中的文档位置进行匹配。您可以向MongoDB Jira项目的SERVER队列提交新功能建议。
听起来你会想要一个新的管道运算符,例如$matchfrom
,它会在第一次出现$matchfrom
条件之前忽略任何文档。然后,您可以添加$limit
以接下来的n个项目。您还希望在$matchfrom
之前排序输出,以便有可预测的结果。
与增加的subjectID相比,这似乎过于复杂,但可能存在基于更高级搜索条件或在聚合管道中计算的结果进行分页的用例。
除了聚合框架中对此类功能的未来支持之外,您还可以选择在代码中实现相同的匹配方法:
使用带有finalize()
函数的旧group()
聚合命令。注意:group()
不使用分片群集。
使用MapReduce和finalize()
函数
从聚合框架中获取整个结果集,并在应用程序代码中实现匹配/减少结果(尽管如果您为每个请求获取所有页面,这有点会失去“分页”概念。)< / p>
skip
的查询仍然需要读取介入的索引条目,因此跳过大量文档效率不高。
您可以考虑通过从上一页的最后一个条目开始执行连续的页面查询,而不是使用跳过偏移进行分页(即,第一页将是$gte
起始主题ID,后续页面将是{{ 1}}上一页中包含的最后一个subjectID)。这将取决于您在用户界面中如何呈现分页 - 如果您的UI只能显示消息的“下一页”而不是跳转到特定页面,则最简单的方法是使用此方法。