mongodb - 在 MongoDB 中为 $lookup 结果添加一个字段

标签 mongodb

我正在尝试使用 node.js MongoDB 驱动程序向查找结果中添加一个字段。用户有两种提要 1. 他或她自己的提要和 2. 共享提要。所以我需要两者兼而有之,然后将它们结合起来。这是我的原始查询,效果很好:

client.db('atlas').collection('users').aggregate([
    { $match: { user_id: userId } },
    {
      $lookup: {
        from: 'feeds',
        localField: "user_id",
        foreignField: "user_id",
        as: "feeds"
      }
    },
    {
      $lookup: {
        from: 'shares',
        localField: 'email',
        foreignField: "share",
        as: "shares"
      }
    },
    {
      $lookup: {
        from: 'feeds',
        localField: 'shares.feed_id',
        foreignField: "_id",
        as: "shared_feeds"
      }
    },
    {
      $addFields: { 'shared_feeds.share': true }
    },
    {
       $project: {
         user_id: 1,
         first_name: 1,
         last_name: 1,
         email: 1,
         feeds: { $concatArrays: [ '$feeds', '$shared_feeds' ] }
       }
    }
])

但我想在“提要”的第二次查找中添加一个字段,所以我尝试使用这样的管道:

{
  $lookup: {
    from: 'feeds',
    let: { shareId: '$shares.feed_id' },
    pipeline: [
      { $match: { '_id': ObjectId('$$shareId') } }
    ],
    as: "shared_feeds"
  }
}

但我无法匹配 ObjectId。该变量似乎不起作用。我做错了什么?

样本集合: 用户:

[
    {
    "_id" : ObjectId("5e970a1f797c08e70ce4e2f6"),
    "user_id" : "testuserid",
    "first_name" : "Jacopo",
    "last_name" : "Belbo",
    "email" : "test@test.com"
   }
]

提要:

 [
  {
      "_id" : ObjectId("5f29b02318ecbf0083f01f1e"),
      "name" : "test csv",
      "user_id" : "auth0|5eac6faa1cc1ac0c147b5b16",
      "type" : "feed",
      "created_at" : ISODate("2020-08-04T18:59:47.640Z"),
      "updated_at" : ISODate("2020-08-04T18:59:47.640Z")
  },
  {
    "_id" : ObjectId("5f29b05d18ecbf0083f01f1f"),
    "name" : "typtap-small",
    "user_id" : "auth0|5f1b2da0e60194003d714680",
    "url" : "http://localstack:4572/atlas/usertes",
    "type" : "feed",
    "created_at" : ISODate("2020-08-04T19:00:45.886Z"),
    "updated_at" : ISODate("2020-08-04T19:00:45.886Z")
  }
]

分享:

[
    {
    "_id" : ObjectId("5f29b07318ecbf0083f01f20"),
    "feed_id" : ObjectId("5f29b05d18ecbf0083f01f1f"),
    "share" : "test@test.com",
    "type" : "share",
    "recipient" : "email",
    "created_at" : ISODate("2020-08-04T19:01:07.668Z"),
    "updated_at" : ISODate("2020-08-04T19:01:07.668Z")
}
]

最佳答案

let: { shareId: '$shares.feed_id' } 中,您将 ObjectId 传递给 shareId。所以你不能在 match 阶段用 ObjectId() 包装。当您在多个条件的查找中使用管道时只需使用 $expr

    {
      $match: {
        $expr: {
          $eq: [
            "$$shareId",
            "$_id"
          ]
        }
      }
    }

更新 1.

当你在$lookup中使用管道时,你需要使用$expr,引用$expr in lookup .一旦你得到输出,你就会有一个数组,所以 $unwind 它并进行连接。然后将其分组以避免重复。

工作 Mongo playground

更新 2

mongo 脚本

[
  {
    $match: {
      user_id: "testuserid"
    }
  },
  {
    $lookup: {
      from: "feeds",
      localField: "user_id",
      foreignField: "user_id",
      as: "feeds"
    }
  },
  {
    $lookup: {
      from: "shares",
      localField: "email",
      foreignField: "share",
      as: "shares"
    }
  },
  {
    $unwind: {
      path: "$shares",
      preserveNullAndEmptyArrays: false
    }
  },
  {
    $lookup: {
      from: "feeds",
      let: {
        shareId: "$shares.feed_id"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$$shareId",
                "$_id"
              ]
            }
          }
        }
      ],
      as: "shared_feeds"
    }
  },
  {
    $group: {
      _id: "$_id",
      user_id: {
        $first: "$user_id"
      },
      first_name: {
        $first: "$first_name"
      },
      last_name: {
        $first: "$last_name"
      },
      email: {
        $first: "$email"
      },
      feeds: {
        $first: "$feeds"
      },
      shares: {
        $addToSet: "$shares"
      },
      shared_feeds: {
        $addToSet: "$shared_feeds"
      }
    }
  },
  {
    $addFields: {
      shared_feeds: {
        $reduce: {
          input: "$shared_feeds",
          initialValue: [],
          in: {
            $setUnion: [
              "$$this",
              "$$value"
            ]
          }
        }
      }
    }
  },
  {
    $addFields: {
      "shared_feeds.share": true
    }
  },
  {
    $project: {
      user_id: 1,
      first_name: 1,
      last_name: 1,
      email: 1,
      feeds: {
        $concatArrays: [
          "$feeds",
          "$shared_feeds"
        ]
      }
    }
  }
]

关于mongodb - 在 MongoDB 中为 $lookup 结果添加一个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63272936/

相关文章:

c# - SQL Server 与 MongoDB : Speed test?

node.js - MongoDB 数据库信号量和 Node.js Process.NextTick()

mongodb - 无法在身份验证模式下使用 Mongo 连接 Mongo-Spark Connector

node.js - 如何通过 NodeJS 的 MongoDB native 驱动程序执行 db.copyDatabase?

node.js - Node JS 中 Celery 的等价物

node.js - Mongoose :无法将嵌套对象保存到嵌套模型

python - mongoengine - 运行时错误 : generator raised StopIteration

javascript - 使用 mongoose 返回特定字段

node.js - Mongoose:在保存时根据父字段值设置子文档字段值

mongodb - 如何通过比较表示层次结构/关系的元素属性来重新映射/过滤嵌套数组的元素?