MongoDB视图关联双集合:$unwind作用及缺失字段留存方案问询
问题原因及解决方案
为什么会丢失记录?
MongoDB默认的$unwind行为是:如果目标字段不存在、为null或者是空数组,执行$unwind后会直接移除整个文档。你的场景里,部分domain记录没有isOpenDomain或isPartnerDomain字段,当对这两个字段执行$unwind时,这些缺失字段的文档就被过滤掉了,所以最终只保留了同时存在这两个字段的记录。
怎么保留所有记录?
有两种可行的解决方式:
方式1:给$unwind添加preserveNullAndEmptyArrays参数
修改$unwind阶段,开启preserveNullAndEmptyArrays: true,这样即使字段不存在、为null或空数组,文档也会被保留下来。
修改后的视图创建语句:
db.createView( "userDomainRelation", "user", [ { $lookup: { from: "domain", localField: "domain", foreignField: "_id", as: "matchDomain" } }, { $project: { _id: 1, email: 1, firstName: 1, lastName: 1, accountType: 1, domain: 1, host: "$matchDomain.host", isOpenDomain: "$matchDomain.isOpenDomain", isPartnerDomain: "$matchDomain.isPartnerDomain" } }, { $unwind: { path: "$host", preserveNullAndEmptyArrays: true } }, { $unwind: { path: "$isOpenDomain", preserveNullAndEmptyArrays: true } }, { $unwind: { path: "$isPartnerDomain", preserveNullAndEmptyArrays: true } } ] )
方式2:先展开matchDomain再提取字段(更推荐)
因为$lookup返回的matchDomain是数组(即使只匹配到一个文档),先对matchDomain执行$unwind,再直接提取里面的字段,这样后续不需要再对单个字段执行$unwind,同时天然支持缺失字段的保留(缺失字段会显示为null)。
这种方式逻辑更清晰,也避免了多层数组的问题:
db.createView( "userDomainRelation", "user", [ { $lookup: { from: "domain", localField: "domain", foreignField: "_id", as: "matchDomain" } }, // 先展开匹配到的domain数组 { $unwind: { path: "$matchDomain", preserveNullAndEmptyArrays: true } }, { $project: { _id: 1, email: 1, firstName: 1, lastName: 1, accountType: 1, domain: 1, host: "$matchDomain.host", isOpenDomain: "$matchDomain.isOpenDomain", isPartnerDomain: "$matchDomain.isPartnerDomain" } } ] )
注:如果你的
user和domain是一对一关联(每个user的domain只对应一个domain文档),这种方式最适合,matchDomain展开后就是单个文档,所有字段直接是单个值,不会出现数组。
内容的提问来源于stack exchange,提问作者DeniseMeander
相关产品推荐
相关产品推荐

