【问题标题】:Issues with lookup and match multipe collections查找和匹配多个集合的问题
【发布时间】:2020-05-09 20:21:02
【问题描述】:

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

我已经尝试添加池作为 let 并在最后阶段将其用作 { $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',在最后一次查找中它会覆盖查找的池数据。

【问题讨论】:

    标签: mongodb mongoose aggregation-framework


    【解决方案1】:

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

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

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

    或将userId: '$userId' 重命名或第二个名称,例如innerUserId: '$userId',以避免在访问时发生冲突。

    之后别忘了把{ $eq: ['$userId', '$$userId'] }改成{ $eq: ['$userId', '$$innerUserId'] }

    编辑:

    既然已经清楚 pools 集合中没有字段 userId,只需将第二个 lookup 集合中的变量更改为:

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

    收件人:

    let: { innerUserId: '$$userId' }
    

    【讨论】:

    • 感谢您的回答,但没有奏效。尝试了删除和重命名,但仍然只得到一个空的优惠券数组
    • 好吧,语法是正确的,所以要么你在ObjectIdstring之类的集合之间存在类型不匹配,要么另一个选项是poolProjectproject userId 字段,我不知道,因为你没有发布它。
    • 池中没有 userId,因为它是一个“通用”集合。 userId 位于顶级 userModel 和第三级优惠券中。我也使用 userId 作为字符串,而不是我认为的 ObjectId?我已经用当前查询和预测更新了问题
    • 啊,您在上面发布的数据表明并非如此,在这种情况下,它很容易解决,因为您只是遇到了一个小的语法错误。我在编辑中指定了它。
    • 如果它是一个“通用”系列,为什么不先匹配优惠券以提高性能?
    猜你喜欢
    • 1970-01-01
    • 2019-03-17
    • 2018-01-21
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多