首页 > 解决方案 > 基于嵌套字段过滤集合的 Mongoose 查询

问题描述

我们想看看 mongoose 是否可以通过繁重的工作来获取给定组织名称和 UserId 的用户角色。

这可以通过首先找出组织数据并使用 javascript 根据用户 ID 过滤掉来轻松完成。但是我认为如果查询可以做到而不是在 mongo 集合之外进行,它会提供更好的性能。

我们想尝试以下类似的方法,但它没有正确地赋予用户角色。

查询(不工作)

    public async getUserOrgRole(orgName: string, userId) {
        const result = await this.organizationModel
            .findOne({ name: orgName, 'orgMembers.userId': userId })
            .select('orgMembers.role')
            .exec();
        if (result) {
            const orgMember = _.get(result, 'orgMembers');
            return orgMember[0].role;
        }
        return null;
    }

查询(工作,但我们希望上述查询工作而不是拉整个文档)

    public async getUserOrgRole(orgName: string, userId) {
        const org = await this.organizationModel.findOne({ name: orgName })
        if (!org)
            return null;
        const userInOrg = org.orgMembers.find(om => om.userId === userId)
        console.log('--getUserOrgRole', userInOrg)
        if (userInOrg)
            return userInOrg.role
        return null;
    }



架构


const UserOrgSchema = new Schema({
    role: { type: Schema.Types.String, enum: ['MEMBER', 'OWNER', 'ADMIN'], default: 'MEMBER' },
    inactive: { type: Schema.Types.Boolean, default: false },
    userId: { type: Schema.Types.String, required: true },
});


const OrganizationSchema = new Schema({
    name: { type: Schema.Types.String, unique: true },
    picture: { type: Schema.Types.String },
    orgMembers: { type: [UserOrgSchema] },
    createdAt: { type: Schema.Types.Date, default: Date.now },
    updatedAt: { type: Schema.Types.Date, default: Date.now },
});

标签: node.jsmongoosemongoose-schema

解决方案


你几乎做对了。Sunil解释了您的尝试不起作用的原因。无论您应用什么过滤器.find(),它都会返回整个文档。如果要选择特定的子文档,则需要使用额外的select运算符来完成。这应该有效:

const result = await this.organizationModel
  .findOne({ name: orgName, "orgMembers.userId": userId })
  .select({
    orgMembers: {
      $elemMatch: {
        userId,
      },
    },
  })
  .select("orgMembers.role")
  .exec();

注意使用$elemMatch!它完全符合您的要求 - 通过仅选择与提供的过滤器匹配的子文档来过滤子文档。


推荐阅读