如何在MongoDB聚合的$project阶段引用外部JavaScript字典
解决方案:在MongoDB聚合$project阶段关联客户端字典值
嘿,这个问题我刚好碰到过,来给你梳理下可行的解决方案!首先得先提个关键小细节:你定义的dict里有重复的"a1"键,JavaScript中对象的重复键会被后面的覆盖,所以要先修正字典为:
let dict = { "a1": "ref1", "a2": "ref2" };
不然最终a1对应的会是ref2,和你期望的输出不符。
接下来分两种场景给你提供实现方式:
方法一:使用$getField(MongoDB 4.4+ 推荐)
MongoDB 4.4及以上版本支持$getField操作符,可以直接从指定对象中提取对应字段的值,非常简洁。因为聚合管道可以直接引用客户端的可序列化变量,所以你可以直接把dict传入$getField的input参数:
this.model.aggregate([ { $match: { uid: { $in: Object.keys(dict) } } }, { $project: { uid: 1, // 保留uid字段 ref: { $getField: { field: "$uid", // 用文档中的uid值作为要获取的字段名 input: dict // 传入客户端定义的字典 } } } } ]);
这个方法代码简洁,性能也不错,适合使用高版本MongoDB的场景。
方法二:使用$switch(兼容低版本MongoDB)
如果你的MongoDB版本低于4.4,无法使用$getField,可以把字典转换成$switch的分支条件,通过匹配uid来返回对应的ref值:
第一步先把字典转换成$switch需要的分支数组:
const switchBranches = Object.entries(dict).map(([uid, ref]) => ({ case: uid, then: ref }));
然后在聚合管道中使用:
this.model.aggregate([ { $match: { uid: { $in: Object.keys(dict) } } }, { $project: { uid: 1, ref: { $switch: { branches: switchBranches, default: null // 当uid没有匹配到字典中的键时,返回null,可根据需求调整 } } } } ]);
这个方法兼容性更好,能适配大部分MongoDB版本,唯一的小缺点是当字典很大时,分支数组会比较长,但对于一般规模的字典完全没问题。
两种方法都能得到你期望的输出:
[{uid: "a1", ref: "ref1"}, {uid: "a2", ref: "ref2"}]
内容的提问来源于stack exchange,提问作者Mike M
相关产品推荐
相关产品推荐

