首页 > 解决方案 > Mongo 同时从 2 个集合中获得价值

问题描述

我正在尝试从 2 个集合中获取数据,并返回一个包含两个集合的合并数据的数组。

对我来说最好的解决方案是:

const bothValues = await ValueA.aggregate([
      { $unionWith: { coll: 'valueB' } },
      { $sort: { rank: -1, _id: -1 } },
      {
        $match: {
          isAvailable: true,
        },
      },
      { $skip: skip },
      { $limit: 30 },
    ]);

完美的工作。但是..$unionWith没有实现我的 MongoDB 版本(4.0.X)所以我不能使用它。

const bothValues = await ValueA.aggregate(
      [
        { $limit: 1 },
        {
          $lookup: {
            from: 'valueB',
            pipeline: [{ $limit: 15 }],
            as: 'valueB',
          },
        },
        {
          $lookup: {
            from: 'ValueA',
            pipeline: [{ $limit: 15 }, { $sort: { rank: -1, _id: -1 } }],
            as: 'ValueA',
          },
        },
        {
          $project:
          {
            Union: { $concatArrays: ['$valueB', '$ValueA'] },
          },
        },
        { $unwind: '$Union' },
        { $replaceRoot: { newRoot: '$Union' } },
      ],
    );

但现在,我遇到了两个问题:

谢谢

标签: javascriptarraysmongodbmongooseunion

解决方案


询问

  • 您的查询进行了一些更改,以像第一个查询一样工作
  • 在两个管道中匹配,在两个管道中排序,(limit limitN+skipN)(这样我们可以确保我们总是有足够的文档,即使所有文档都来自 valueA 或 valueB)
  • 从每个中取出已排序的 70,因此无论如何我们将在联合之后的最终排序/跳过/限制中获得所需的 70。
  • concat,unwind,replace-root 就像您的查询一样
  • 再次排序(现在对联合进行排序),跳过,限制
  • 不管我们总是有足够的文件可以跳过
  • 这个示例查询是针对的 skip=40limit=30所以在前 2 个管道中,我们limit=70
db.ValueA.aggregate([
  {
    "$limit": 1
  },
  {
    "$lookup": {
      "from": "valueB",
      "pipeline": [
        {
          "$match": {
            "isAvailable": true
          }
        },
        {
          "$sort": {
            "rank": -1,
            "_id": -1
          }
        },
        {
          "$limit": 70
        }
      ],
      "as": "valueB"
    }
  },
  {
    "$lookup": {
      "from": "valueA",
      "pipeline": [
        {
          "$match": {
            "isAvailable": true
          }
        },
        {
          "$sort": {
            "rank": -1,
            "_id": -1
          }
        },
        {
          "$limit": 70
        }
      ],
      "as": "valueA"
    }
  },
  {
    "$project": {
      "union": {
        "$concatArrays": [
          "$valueA",
          "$valueB"
        ]
      }
    }
  },
  {
    "$unwind": {
      "path": "$union"
    }
  },
  {
    "$replaceRoot": {
      "newRoot": "$union"
    }
  },
  {
    "$sort": {
      "rank": -1,
      "_id": -1
    }
  },
  {
    "$skip": 40
  },
  {
    "$limit": 30
  }
])

推荐阅读