Mongodb从String到ObjectId加入_id字段

时间:2016-12-12 03:07:02

标签: mongodb join aggregation-framework lookup objectid

我有两个收藏品

  1. 用户

             {
                 "_id" : ObjectId("584aac38686860d502929b8b"),
                 "name" : "John"
             }
    
  2. 作用

     {
         "_id" : ObjectId("584aaca6686860d502929b8d"),
         "role" : "Admin",
         "userId" : "584aac38686860d502929b8b"  
     }
    
  3. 我想基于 userId (在角色集合中)加入这些集合 - _id (在用户 >收藏)。

    我尝试了以下查询:

    db.role.aggregate(
    {
       $lookup:
       {
           from: 'user',
           localField: 'userId',
           foreignField: '_id',
           as: 'output'
       }
    }
    );
    

    只要我将userId存储为ObjectId,这就给了我预期的结果。当我的userId是一个字符串时,没有结果。 Ps:我试过了

      

    foreignField:' _id' .valueOf()

      

    foreignField:' _id' .toString()

    。但是基于ObjectId-string字段匹配/加入没有运气。

    任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:13)

您可以使用mongodb 4.0 中的$toObjectId聚合,它将字符串for dict in list: for key, value in dict.iteritems(): # do something with key or value 转换为id

ObjectId

或者您可以使用mongodb 4.0 中的$toString聚合将db.role.aggregate([ { "$lookup": { "from": "user", "let": { "userId": "$_id" }, "pipeline": [ { "$addFields": { "userId": { "$toObjectId": "$userId" }}}, { "$match": { "$expr": { "$eq": [ "$userId", "$$userId" ] } } } ], "as": "output" }} ]) 转换为ObjectId

String

答案 1 :(得分:9)

从MongoDB 3.4开始,这是不可能的。此功能已被请求,但尚未实施。以下是相应的门票:

现在你必须将userId存储为ObjectId

修改

之前的门票已在MongoDB 4.0中修复。您现在可以使用以下查询来实现此目的:

db.user.aggregate([
  {
    "$project": {
      "_id": {
        "$toString": "$_id"
      }
    }
  },
  {
    "$lookup": {
      "from": "role",
      "localField": "_id",
      "foreignField": "userId",
      "as": "role"
    }
  }
])

结果:

[
  {
    "_id": "584aac38686860d502929b8b",
    "role": [
      {
        "_id": ObjectId("584aaca6686860d502929b8d"),
        "role": "Admin",
        "userId": "584aac38686860d502929b8b"
      }
    ]
  }
]

在线试用:mongoplayground.net/p/JoLPVIb1OLS

答案 2 :(得分:0)

我认为先前的答案在'$ toObjectId'情况下有错误。 let语句适用于在其上调用功能aggregate(即'role')的db集合,而不适用于“ from”(即'user')所指向的集合。

db.role.aggregate([
  { "$lookup": {
    "let": { "userObjId": { "$toObjectId": "$userId" } },
    "from": "user",
    "pipeline": [
      { "$match": { "$expr": { "$eq": [ "$_id", "$$userObjId" ] } } }
    ],
    "as": "userDetails"
  }}
])

db.role.aggregate([
  { "$project": { "userObjId": { "$toObjectId": "$userId" } } },
  { "$lookup": {
    "localField": "userObjId",
    "from": "user",
    "foreignField": "$_id",
    "as": "userDetails"
  }}
])

db.user.aggregate([
  { "$project": { "userStrId": { "$toString": "$_id" }}},
  { "$lookup": {
    "localField": "userStrId",
    "from": "role",
    "foreignField": "userId",
    "as": "roleDetails"
  }}
])