【问题标题】:Mongoose query to filter the collection based on nested field基于嵌套字段过滤集合的 Mongoose 查询
【发布时间】:2020-10-31 18:51:10
【问题描述】:

我们想看看 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 },
});

【问题讨论】:

  • 您使用的条件实际上意味着 => 获得一个名为 orgName 的组织,并且 orgMembers 至少有一个具有您指定的 userId 的成员。这意味着此查询未选择确切的用户。但组织本身。所以它返回了整个组织。不是用户。
  • @SunilKSamanta 我们希望第一个查询能够工作。第二个查询按预期工作,但为什么第一个查询不工作?

标签: node.js mongoose mongoose-schema


【解决方案1】:

你几乎猜对了。 Sunil 解释了您的尝试不完全奏效的原因。无论您对.find() 应用什么过滤器,它都将始终返回整个文档。如果要选择特定的子文档,则需要使用附加的 select 运算符来执行此操作。这应该有效:

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

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

【讨论】:

    猜你喜欢
    • 2018-03-22
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 2019-06-14
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    相关资源
    最近更新 更多