首页 > 解决方案 > 查找和匹配多重集合的问题

问题描述

在多个阶段存在聚合和查找问题。问题是我无法userId在最后一次查找中匹配。如果我省略{ $eq: ['$userId', '$$userId'] }它,它会起作用并与其他标准匹配。但不是由userid.

我已经尝试将添加的池作为一个让,并{ $eq: ['$userId', '$$pools.userId'] }在最后一个阶段使用它,但这也不起作用。我得到一个空的优惠券数组。

我通过以下查询得到了这个。我想我需要以$unwind某种方式使用?但还没有开始工作。任何指针?

共有三个集合要加入。首先是 userModel,它应该包含池,然后池应该包含用户优惠券。

{
   "userId": "5df344a1372f345308dac12a", // Match this usedId with below userId coming from the coupon

   "pools": [
               {
                "_id": "5e1ebbc6cffd4b042fc081ab",
                "eventId": "id999",
                "eventStartTime": "some date",
                "trackName": "tracky",
                "type": "foo bar",
                "coupon": []
               }
            ]
  },

我需要用正确的数据(如下)填充优惠券数组,其中包含匹配的 userId。

"coupon": [
                {
                    "eventId": "id999",
                    "userId": "5df344a1372f345308dac12a",  // This userId need to match the above one
                    "checked": true,
                    "pool": "a pool",
        }           

池项目:

const poolProject = {
    eventId: 1,
    eventStartTime: 1,
    trackName: 1,
    type: 1,
  };

用户项目:

const userProjection = {
    _id: {
      $toString: '$_id',
    },
    paper: 1,
    correctBetsLastWeek: 1,
    correctBetsTotal: 1,
    totalScore: 1,
    role: 1,
  };

聚合查询

  const result = await userModel.aggregate([
{ $project: userProjection },
{
  $match: {
    $or: [{ role: 'User' },
      { role: 'SuperUser' }],
  },
},
{ $addFields: { userId: { $toString: '$_id' } } },
{
  $lookup: {
    from: 'pools',
    as: 'pools',
    let: { eventId: '$eventId' },
    pipeline: [
      { $project: poolProject },
      {
        $match: {
          $expr: {
            $in: ['$eventId', eventIds],
          },
        },
      },
      {
        $lookup: {
          from: 'coupons',
          as: 'coupon',
          let: { innerUserId: '$$userId' },
          pipeline: [
            {
              $match: {
                $expr: {
                  $eq: ['$userId', '$$innerUserId'],
                },
              },
            },
          ],
        },
      },
    ],
  },
},
]);

感谢您的任何意见!

编辑:如果我移动第二个查找(优惠券),使它们处于相同的“级别”,它可以工作,但我希望将它放在池中。如果我添加as: 'pools.coupon',在最后一次查找中它会覆盖查找池数据。

标签: mongodbmongooseaggregation-framework

解决方案


当您访问带有$$前缀的字段时,这意味着它们被 Mongo 定义为“特殊”系统变量。

我们不确切知道 Mongo 的魔法是如何发生的,但是您用相同的名称命名了两个变量,这似乎会导致冲突。

所以要么userId: '$userId'从第一次查找中删除,因为你甚至没有使用它。

或者重命名或第二userId: '$userId'个不同的名称,innerUserId: '$userId'以避免在访问时发生冲突。

只是不要忘记更改{ $eq: ['$userId', '$$userId'] }{ $eq: ['$userId', '$$innerUserId'] }之后。

编辑:

现在很明显集合中没有字段userIdpools只需将第二个集合中的变量lookup从以下位置更改:

let: { innerUserId: '$userId' } //userId does not exist in pools.

至:

let: { innerUserId: '$$userId' }

推荐阅读