Mongo db - 如何使用分页连接和排序两个集合

Mongo db - how to join and sort two collection with pagination

我有 2 个合集:

  1. 办公室-
{
  _id: ObjectId(someOfficeId),
  name: "some name",
  ..other fields
}
  1. 文件-
{
  _id: ObjectId(SomeId),
  name: "Some document name",
  officeId: ObjectId(someOfficeId),
  ...etc
}

我需要获取按涉及办公室的文档数排序的办公室列表。还要实现分页。

我尝试通过聚合和使用 $lookup

来做到这一点
const aggregation = [
        {
            $lookup: {
                from: 'documents',
                let: {
                    id: '$id'
                },
                pipeline: [
                    {
                        $match: {
                            $expr: {
                                $eq: ['$officeId', '$id']
                            },
                            // sent_at: {
                            //     $gte: start,
                            //     $lt: end,
                            // },
                        }
                    }
                ],
                as: 'documents'
            },
        },
        { $sortByCount:  "$documents" },
        { $skip: (page - 1) * limit },
        { $limit: limit },
    ];

但这对我不起作用

任何想法如何实现这个?

p.s。我需要显示包含 0 个文件的办公室,所以通过 documets 获取办公室 - 对我不起作用

查询

  • 您可以使用 lookup 加入该字段,并通过管道进行分组,这样您就可以计算每个办公室的文档(而不是将文档放入数组中,因为您只计算计数)
  • $set 是在顶级字段中获取该计数
  • 使用 noffices 字段排序
  • 你可以使用skip/limit的方式进行分页,但是如果你的collection很大,它会很慢见this。或者,您可以使用 _id 自然顺序进行分页,或者在每个查询中检索更多文档并将它们保存在内存中(而不是只检索一页的文档)

Test code here

offices.aggregate(
[{"$lookup":
  {"from":"documents",
   "localField":"_id",
   "foreignField":"officeId",
   "pipeline":[{"$group":{"_id":null, "count":{"$sum":1}}}],
   "as":"noffices"}},
 {"$set":
  {"noffices":
   {"$cond":
    [{"$eq":["$noffices", []]}, 0,
     {"$arrayElemAt":["$noffices.count", 0]}]}}},
 {"$sort":{"noffices":-1}}])

正如另一个答案所指出的,您忘记了 id_,但您不需要 let 或在管道内与 $expr 匹配,通过上面的查找。另外 $sortByCount 不计算数组的成员,您需要 $size (按计数排序只是分组,而不是对数组进行计数)。但是你不需要 $size 你也可以像上面那样在管道中计算它们。


编辑

查询

  • 您可以在管道中添加您需要的内容或直接删除它
  • 这会保留所有文档,并计算数组大小
  • 然后排序

Test code here

offices.aggregate(
[{"$lookup":
  {"from":"documents",
   "localField":"_id",
   "foreignField":"officeId",
   "pipeline":[],
   "as":"alldocuments"}},
 {"$set":{"ndocuments":{"$size":"$alldocuments"}}},
 {"$sort":{"ndocuments":-1}}])

您的查询有两个错误

同时使用 $let 传递变量。您忘记了 $_id 本地字段

_
let: {
    id: '$id'
},

$exp 中,因为您使用的是变量 id 而不是 Documents 集合,你应该使用 $$ 来引用变量。

$expr: {
    $eq: ['$officeId', '$$id']
},