联合 2 个表,就像它是单个实体一样,然后排序、跳过和限制 (Mongoose)

Union 2 tables like it is a single entity, then sort, skip, and limit (Mongoose)

我有 2 个模式,模式 A 和 B,如下所示:

const A = new Schema({
  paymentId: Number,
  date: Date,
  ...data
})

const B = new Schema({
  paidId: Number,
  date: Date,
  ...data
})

我想 return 来自 A 和 B 的记录,就像它是单个 table,我可以从 A 和 B 中获取可与 .sort() 一起使用的记录、.skip().limit() 功能理想。

我可以在两个 table 上做一个 .find(),连接它们,然后手动排序/跳过/限制,但我发现效率非常低。

编辑:澄清一下。这两个集合是否相关并不重要。我只想从两个集合中查询,就像它们都在一个集合中一样。

例如,如果我有以下文件

// Documents in A
{ date: '2020-01-01', A_id: 1 },
{ date: '2020-01-03', A_id: 2 },
{ date: '2020-01-05', A_id: 3 },

// Documents in B
{ date: '2020-01-02', B_id: 1 },
{ date: '2020-01-04', B_id: 2 },
{ date: '2020-01-06', B_id: 3 },

使用选项 .sort('date').skip(0).limit(5) 进行查询应该得到以下结果:

// Documents in A and B
{ date: '2020-01-01', A_id: 1 },
{ date: '2020-01-02', B_id: 1 },
{ date: '2020-01-03', A_id: 2 },
{ date: '2020-01-04', B_id: 2 },
{ date: '2020-01-05', A_id: 3 },
//Can I suggest, $merge to merge these two independent collections into another different collection 
//and then use aggregation to doing sort(),skip() and limit()
> db.version();
4.2.6
> db.colA.find();
{ "_id" : ObjectId("5f76d969975ec8826bbcaab5"), "date" : "2020-01-01", "A_id" : 1 }
{ "_id" : ObjectId("5f76d969975ec8826bbcaab6"), "date" : "2020-01-03", "A_id" : 2 }
{ "_id" : ObjectId("5f76d969975ec8826bbcaab7"), "date" : "2020-01-05", "A_id" : 3 }
> db.colB.find();
{ "_id" : ObjectId("5f76d969975ec8826bbcaab8"), "date" : "2020-01-02", "B_id" : 1 }
{ "_id" : ObjectId("5f76d969975ec8826bbcaab9"), "date" : "2020-01-04", "B_id" : 2 }
{ "_id" : ObjectId("5f76d969975ec8826bbcaaba"), "date" : "2020-01-06", "B_id" : 3 }
> db.colA.aggregate([
{$match:{}},
{$merge:{into: "colAB"}}
]);
>db.colB.aggregate([
{$match:{}},
{$merge:{into: "colAB"}}
]);
> db.colAB.find();
{ "_id" : ObjectId("5f76d969975ec8826bbcaab5"), "A_id" : 1, "date" : "2020-01-01" }
{ "_id" : ObjectId("5f76d969975ec8826bbcaab6"), "A_id" : 2, "date" : "2020-01-03" }
{ "_id" : ObjectId("5f76d969975ec8826bbcaab7"), "A_id" : 3, "date" : "2020-01-05" }
{ "_id" : ObjectId("5f76d969975ec8826bbcaab8"), "B_id" : 1, "date" : "2020-01-02" }
{ "_id" : ObjectId("5f76d969975ec8826bbcaab9"), "B_id" : 2, "date" : "2020-01-04" }
{ "_id" : ObjectId("5f76d969975ec8826bbcaaba"), "B_id" : 3, "date" : "2020-01-06" }
> > db.colAB.aggregate([
... {$project:{_id:0}},
... {$sort:{date:1}},
... {$skip:0},
... {$limit:5}
... ]);
{ "A_id" : 1, "date" : "2020-01-01" }
{ "B_id" : 1, "date" : "2020-01-02" }
{ "A_id" : 2, "date" : "2020-01-03" }
{ "B_id" : 2, "date" : "2020-01-04" }
{ "A_id" : 3, "date" : "2020-01-05" }

来自

Doing unions in MongoDB in a 'SQL UNION' fashion is possible using aggregations along with lookups, in a single query.

Something like this:

    db.getCollection("AnyCollectionThatContainsAtLeastOneDocument").aggregate(
    [
      { $limit: 1 }, // Reduce the result set to a single document.
      { $project: { _id: 1 } }, // Strip all fields except the Id.
      { $project: { _id: 0 } }, // Strip the id. The document is now empty.

      // Lookup all collections to union together.
      { $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } },
      { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } },
      { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } },

      // Merge the collections together.
      {
        $project:
        {
          Union: { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
        }
      },

      { $unwind: "$Union" }, // Unwind the union collection into a result set.
      { $replaceRoot: { newRoot: "$Union" } } // Replace the root to cleanup the resulting documents.
    ]);

更多详细信息在上面的 post 中。添加 $sort$skip$limit 只是将它们添加到聚合管道的问题。非常感谢@sboisse!