Mongodb在_id字段上从字符串连接到ObjectId

Mongodb在_id字段上从字符串连接到ObjectId,mongodb,join,mongodb-query,aggregation-framework,lookup,Mongodb,Join,Mongodb Query,Aggregation Framework,Lookup,我有两套 使用者 { "_id" : ObjectId("584aac38686860d502929b8b"), "name" : "John" } 角色 { "_id" : ObjectId("584aaca6686860d502929b8d"), "role" : "Admin", "userId" : "584aac38686860d502929b8b" } 我想根据用户id(在角色集合中)\u id(在用户集合中)加入这些集合 我尝试了以下查询:

我有两套

  • 使用者

    {
       "_id" : ObjectId("584aac38686860d502929b8b"),
       "name" : "John"
    }
    
  • 角色

    {
       "_id" : ObjectId("584aaca6686860d502929b8d"),
       "role" : "Admin",
       "userId" : "584aac38686860d502929b8b"  
    }
    
  • 我想根据用户id(在角色集合中)\u id(在用户集合中)加入这些集合

    我尝试了以下查询:

    db.role.aggregate({
      "$lookup": {
        "from": "user",
        "localField": "userId",
        "foreignField": "_id",
        "as": "output"
      }
    })
    
    只要我将userId存储为ObjectId,就会得到预期的结果。当我的userId是字符串时,没有结果。 Ps:我试过了

    foreignField:“_id”.valueOf()

    foreignField:“_id”.toString()

    。但是基于ObjectId字符串字段匹配/连接没有运气


    任何帮助都将不胜感激。

    从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"
          }
        ]
      }
    ]
    
    在线试用:

    您可以使用mongodb的聚合4.0将字符串
    id
    转换为
    ObjectId

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

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

    我认为前面的答案在
    $toObjectId
    案例中有一个错误。
    let
    语句适用于调用函数
    aggregate
    的db集合(即“角色”),而不适用于由“from”(即“用户”)指向的集合


    请注意,这2个聚合运算符仅在4中可用。0@AnthonyWinzlet这应该是公认的答案。您好@ash,您在
    cond
    中的括号错误,这应该可以:
    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"
      }}
    ])