You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用MongoDB C#驱动匹配包含全部指定角色内嵌文档的用户文档

问题描述

我有一个名为Users的MongoDB集合,文档结构如下:

{ 
    "_id": ObjectId("5ded105e90424e1c0e6fda04"), 
    "username": "user1", 
    "roles": [
                {"_id" : ObjectId("3aded105e90424e1c0e6fb542"), "name":"admin"},
                {"_id" : ObjectId("5ded105e90424e1c0e6fda05"), "name": "fin"},
            ]
},
{ 
    "_id": ObjectId("5ded105e90424e1c0e6fda05"), 
    "username": "user2", 
    "roles": [
                {"_id" : ObjectId("3aded105e90424e1c0e6fb542"), "name":"admin"},
                {"_id" : ObjectId("5ded105e90424e1c0e6fda05"), "name":"fin"},
            ]
},
{ 
    "_id": ObjectId("5ded105e90424e1c0e6fda06"), 
    "username": "user3", 
    "roles": [
                {"_id" : ObjectId("9bded105e45624e1c0e6fb289"), "name":"basic"},
                {"_id" : ObjectId("5ded105e90424e1c0e6fda05"), "name": "fin"},
            ]
}

需要筛选出roles字段包含指定数组arr = [ObjectId("3aded105e90424e1c0e6fb542"), ObjectId("5ded105e90424e1c0e6fda05")]中所有元素的文档(即同时拥有admin和fin角色的用户,预期结果是user1和user2)。

注意:如果roles是简单的ID数组而非内嵌文档数组,可直接用.All操作符实现:

filter &= Builders<Users>.Filter.All(
                    doc => doc.Roles,
                    Ids)
解决方案

当roles是内嵌文档数组时,需要确保每个指定的角色ID都能在roles数组的某个元素的_id字段中找到,以下两种方式均可实现需求:

方式一:多ElemMatch条件组合

为每个目标角色ID创建一个ElemMatch条件,指定roles数组中存在对应_id的元素,再用And组合所有条件:

var targetRoleIds = new List<ObjectId>
{
    ObjectId.Parse("3aded105e90424e1c0e6fb542"),
    ObjectId.Parse("5ded105e90424e1c0e6fda05")
};

var filterBuilder = Builders<Users>.Filter;
var filters = targetRoleIds.Select(id => 
    filterBuilder.ElemMatch(doc => doc.Roles, role => role._id == id)
);

var finalFilter = filterBuilder.And(filters);

var result = await collection.Find(finalFilter).ToListAsync();

方式二:All操作符结合内嵌字段路径

直接针对roles._id字段使用All操作符,利用MongoDB的字段路径语法简化查询:

var targetRoleIds = new List<ObjectId>
{
    ObjectId.Parse("3aded105e90424e1c0e6fb542"),
    ObjectId.Parse("5ded105e90424e1c0e6fda05")
};

// 强类型写法
var filter = Builders<Users>.Filter.All(doc => doc.Roles[-1]._id, targetRoleIds);

// 或直接使用字符串字段路径
// var filter = Builders<Users>.Filter.All("roles._id", targetRoleIds);

var result = await collection.Find(filter).ToListAsync();

两种方式都能准确筛选出同时包含所有指定角色ID的用户文档,得到预期的user1和user2。

内容的提问来源于stack exchange,提问作者LightTechnician

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 00:18:20