Mongodb从String到ObjectId加入_id字段

Kav*_*ali 17 lookup join mongodb aggregation-framework objectid

我有两个系列

  1. 用户

             {
                 "_id" : ObjectId("584aac38686860d502929b8b"),
                 "name" : "John"
             }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 角色

     {
         "_id" : ObjectId("584aaca6686860d502929b8d"),
         "role" : "Admin",
         "userId" : "584aac38686860d502929b8b"  
     }
    
    Run Code Online (Sandbox Code Playgroud)

我想基于userId(在角色集合中) - _id(在用户集合中)加入这些集合.

我尝试了以下查询:

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

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

foreignField:'_ id'.valueOf()

foreignField:'_ id'.toString()

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

任何帮助将不胜感激.

小智 30

我认为之前的答案在$toObjectId案例中存在错误。该let语句适用于aggregate调用该函数的数据库集合(即'role'),而不适用于“from”指向的集合(即'user')。

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

或者

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

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


Ash*_*shh 17

您可以使用 $toObjectIdmongodb 4.0中的聚合将字符串转换idObjectId

db.role.aggregate([
  { "$lookup": {
    "from": "user",
    "let": { "userId": "$_id" },
    "pipeline": [
      { "$addFields": { "userId": { "$toObjectId": "$userId" }}},
      { "$match": { "$expr": { "$eq": [ "$userId", "$$userId" ] } } }
    ],
    "as": "output"
  }}
])
Run Code Online (Sandbox Code Playgroud)

或者您可以使用$toStringmongodb 4.0中的聚合转换ObjectIdString

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

  • 请注意,这 2 个聚合运算符仅从 4.0 开始可用 (2认同)
  • @AnthonyWinzlet现在应该可以接受这个答案。 (2认同)

fel*_*lix 16

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

现在,您必须将userId存储为ObjectId