我尝试使用 mongoose 查询具有唯一列和分页的 mongo 集合。
我有分页数据,我需要知道总的唯一计数、偏移量/页码,但需要在没有
$skip
和 $limit
的情况下执行查询,这会返回整个集合并消耗内存只是为了获取计数。我尝试使用不同的
await Token.find().distinct('token_id').countDocuments().exec()
这没有给出正确的唯一计数。
在 mongo 上工作了一段时间,据我所知,聚合会收集所有记录,然后过滤/分组并将结果发送回来。只要节点应用程序不执行任何内存密集型操作,这对我来说就很好。
那么,如何实现总的唯一记录(如果可能的话,不获取集合,仅获取计数)和分页以正确的方式工作。
下面是猫鼬模型
Token
并按 token_id
分组以获取唯一记录。 (预计可能会有重复token_id
)
const getUniqueTokens = async () => {
return Token.aggregate([{
$group: {
_id: `$token_id`,
// Get the first document for each unique field
doc: {
$first: "$$ROOT"
}
}
},
{
$replaceRoot: {
// Replace root to get back the original document structure
newRoot: "$doc"
}
},
{
$skip: offset,
},
{
$limit: 100
}
]).exec();
};
您的聚合管道大部分都很好 - 您应该添加一个
$sort
阶段,以便始终可靠地对 1、2、3、4 进行分页。而不是有时 3、2、1、4 次,其他时候 2、4、1、3 次。
$count
阶段来获取总的唯一记录;并将其作为单独的聚合执行。
聚合管道和Mongo Playground用于分页:
db.token.aggregate([
{
$group: {
_id: "$token_id",
// Get the first document for each unique field
doc: { $first: "$$ROOT" }
}
},
{
$replaceRoot: {
// Replace root to get back the original document structure
newRoot: "$doc"
}
},
{ $sort: { token_id: 1 } },
{ $skip: offset },
{ $limit: 100 }
])
聚合管道和 Mongo Playground 总计:
db.token.aggregate([
{
$group: {
_id: "$token_id",
// Get the first document for each unique field
doc: {
$first: "$$ROOT"
}
}
},
{ $count: "total" }
])
$unionWith
在一次聚合中完成这两项操作,但我不建议这样做,因为获取结果然后从实际文档中单独提取“总计”项目是一种不必要的复杂化。