MongoDB查询:找出成员数组被其他文档数组完全包含的文档
MongoDB 数组完全包含关系查询方案
原始文档数据
{ 'name': 'test1', 'members': [1, 2, 3] }, { 'name': 'test2', 'members': [2, 3] }, { 'name': 'test3', 'members': [1, 2, 3, 4, 5] }
查询需求
找出集合中所有members数组被其他文档的members数组完全包含的文档,预期输出:
{ 'shadowed': 'test1', 'shadowed_by': ['test3'] }, { 'shadowed': 'test2', 'shadowed_by': ['test1', 'test3'] }
注:test3的成员数组未被任何其他文档包含,因此不返回。
现有查询的局限性
当前提供的聚合查询仅能匹配数组完全相同的文档,无法处理子集包含的场景:
db.objects.aggregate([ {"$match": {}}, {"$group" : { "_id": {"value": "$members"}, "objects": {"$addToSet":"$name"}, "count": {"$sum":1}}}, {"$match": {"_id": {"$ne": null}, "count":{"$gte":2}}}, {"$project": {"objects": 1, "value": "$_id", "_id":0}} ])
正确的聚合查询方案
db.objects.aggregate([ // 自关联集合,筛选出包含当前文档members的其他文档 { $lookup: { from: "objects", let: { currentMembers: "$members", currentName: "$name" }, pipeline: [ { $match: { $expr: { $and: [ { $ne: ["$name", "$$currentName"] }, // 排除自身文档 { $setIsSubset: ["$$currentMembers", "$members"] } // 判断当前数组是否为对方的子集 ] } } }, { $project: { name: 1, _id: 0 } } ], as: "shadowed_by" } }, // 过滤掉未被任何文档包含的记录 { $match: { $expr: { $gt: [{ $size: "$shadowed_by" }, 0] } } }, // 整理成需求的输出格式 { $project: { _id: 0, shadowed: "$name", shadowed_by: { $map: { input: "$shadowed_by", as: "item", in: "$$item.name" } } } } ])
关键逻辑说明
$lookup自关联:通过$setIsSubset判断当前文档的members是否为其他文档members的子集,同时排除自身文档。- 过滤空结果:仅保留存在被包含关系的文档。
- 格式整理:通过
$map提取shadowed_by中的名称字段,生成符合要求的输出结构。
内容的提问来源于stack exchange,提问作者r6danl99
相关产品推荐
相关产品推荐

