如何使用$ arrayElemAt并从MongoDB $ projection中的该元素中删除字段? [英] How to use $arrayElemAt and remove fields from that element in MongoDB $projection?

查看:955
本文介绍了如何使用$ arrayElemAt并从MongoDB $ projection中的该元素中删除字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有工作"和用户"集合.每个用户都可以为给定的"jobCategoryId"创建一个作业,然后将该作业保存在"jobs"集合中,并包含其创建者的"userId"和"jobCategoryId".

I have 'jobs' and 'users' collection. Every user can create a job for given 'jobCategoryId', that job is then saved in 'jobs' collection and contains 'userId' of it's creator and 'jobCategoryId'.

我试图将这两个集合组合在一起,所以当我获取作业时,我将使用"user"字段和所有用户数据,而不是该作业的"userId"字段.这是我目前的做法:

I'm trying to combine these 2 collections so when I fetch jobs, I'll have 'user' field with all user data instead of 'userId' field for that job. This is how I'm doing it at the moment:

Job.aggregate([{
  $match: {
    jobCategoryId: mongoose.Types.ObjectId(jobCategoryId)
  }
}, {
  $lookup: {
    from: 'users',
    localField: 'userId',
    foreignField: '_id',
    as: 'user'
  }
}, {
  $project: {
    _id: 1,
    description: 1,
    title: 1,
    user: { $arrayElemAt: ['$user', 0] }
  }
}, {
  $project: {
    _id: 1,
    title: 1,
    description: 1,
    'user.name': '$user.name'
  }
}])

这将返回以下内容:

[{
  _id: 'some id',
  title: 'title',
  description: 'description',
  user: {
    name: 'Mike'
  }
}]

结果是正确的,但我真的很感兴趣,是否还有其他方法可以在使用$ arrayElemAt时仅直接保留用户对象中的某些字段,还是我注定要在管道中使用2个投影? 有人可以帮我解决这个小问题吗?我真的很感激.

result is correct but I'm really interested if there is any other way to keep only some fields from user object directly while using $arrayElemAt or am I doomed to use 2 projections in pipeline? Could anyone help me with this little problem? I'd really appreciate it.

推荐答案

这来自 arrayElemAt

表达式可以是任何有效的表达式,只要它 解析为数组.

The expression can be any valid expression as long as it resolves to an array.

这意味着您可以根据需要构造数组元素.在您的情况下,您只需要名称.所以这应该工作:

Which means you can construct your array elements however you want. In your case you want only the name. So this should work:

[{
  $match: {
    jobCategoryId: mongoose.Types.ObjectId(jobCategoryId)
  }
}, {  
  $lookup: {  
    from: 'users',
    localField: 'userId',
    foreignField: '_id',
    as: 'user'
  }
}, {  
  $project: {  
    _id: 1,
    description: 1,
    title: 1,
    user: {  
      name: {
        $arrayElemAt: ["$user.name", 0]
      }
    }
  }
}]

跟进更新: 有人问如何在name之上添加其他属性.这是项目:

Follow up UPDATE: it was asked how to additional properties on top of name . Here is the project:

{  
  $project: {  
    _id: 1,
    description: 1,
    title: 1,
    user: {  
      name: {  
        $arrayElemAt: ["$user.name", 0]
      },
      email: {  
        $arrayElemAt: ["$user.email", 0]
      }
    }
  }
}

第二次跟进,如Drag0在评论中所问:如果上述操作还不够好,因为结果生成了大小为1的user:[]数组,而不是对象user:{},可以使用以下内容.

Second follow up as Drag0 asked in the comments: If the above isn't good enough because the results generate a user:[] array of size 1 instead of an object user:{} the following can be used.

{  
  $project: {
    _id: 1,
    description: 1,
    title: 1,
    user: {
      $let: {
        vars: {
          firstUser: {
            $arrayElemAt: ["$user", 0]
          }
        },
        in: {
          name: "$$firstUser.name",
          email: "$$firstUser.email"
        }
      }
    }
  }
}

这篇关于如何使用$ arrayElemAt并从MongoDB $ projection中的该元素中删除字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆