自动将外键从字符串转换为ObjectId,以使MongoDB中的$lookup聚合正常工作。

huangapple go评论62阅读模式
英文:

Auto conversion of foreign key from string to ObjectId to make $lookup aggregation work by MongoDB

问题

我有两个集合,我正在使用其中一个集合的_id字段作为外键在另一个集合中。但_idObject,在另一个集合中是string,所以$lookup无法匹配。

集合1:User集合

{ "_id" : ObjectId("6471bf9db77f0b33a9b0bd38"), "name" : "Alok", "city" : "someCity" }

集合2:Order集合

{ "_id" : ObjectId("6471bfd4b77f0b33a9b0bd39"), "uid" : "6471bf9db77f0b33a9b0bd38", "product" : "product1" }

我尝试使用$lookup

db.order.aggregate([{$lookup: {from: 'users', localField:'uid', foreignField:'_id', as:'join'}}])

这个$lookup不起作用,因为_id是Object,而uid是string。

这是一个常见的需求,所以必须有一种自动化的方法,因为我不想使用长的pipeline

如何快速修复使这个$lookup工作,而不使用长的pipeline

英文:

I have two collections and I am using one of collections _id field as foreign key in other collection. But _id is Object and in in other collection it is string so $lookup is not able to match.

Collection 1: User collection

{ "_id" : ObjectId("6471bf9db77f0b33a9b0bd38"), "name" : "Alok", "city" : "someCity" }

Collection 2: Order collection

{ "_id" : ObjectId("6471bfd4b77f0b33a9b0bd39"), "uid" : "6471bf9db77f0b33a9b0bd38", "product" : "product1" }

I am trying to use $lookup

db.order.aggregate([{$lookup: {from: 'users', localField:'uid', foreignField:'_id', as:'join'}}])

This $lookup does not work because _id is Object and uid is string.

This is common requirement so there must be some automated way as I dont want to use $lookup with long pipeline.

What can quickest fix to make this $lookup work without using long pipeline?

答案1

得分: 1

如评论中所提到的,您需要在 $lookup 阶段之前使用 $set 阶段将 uid 转换为 ObjectId 类型。

{
  "$set": {
    "uid": {
      "$toObjectId": "$uid"
    }
  }
}

否则,您也可以使用带有管道的 $lookup

{
  "$lookup": {
    "from": "users",
    "let": {
      "uid": {
        "$toObjectId": "$uid"
      }
    },
    "pipeline": [
      {
        "$match": {
          "$expr": {
            "$eq": [
              "$_id",
              "$$uid"
            ]
          }
        }
      }
    ],
    "as": "join"
  }
}
英文:

As mentioned in the comment, you need a $set stage to convert the uid to ObjectId type before $lookup stage.

db.order.aggregate([
  {
    $set: {
      uid: {
        $toObjectId: "$uid"
      }
    }
  },
  {
    $lookup: {
      from: "users",
      localField: "uid",
      foreignField: "_id",
      as: "join"
    }
  }
])

Otherwise, you may use $lookup with pipeline as well.

db.order.aggregate([
  {
    $lookup: {
      from: "users",
      let: {
        uid: {
          $toObjectId: "$uid"
        }
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$_id",
                "$$uid"
              ]
            }
          }
        }
      ],
      as: "join"
    }
  }
])

huangapple
  • 本文由 发表于 2023年5月28日 11:33:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76349828.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定