mongodb - 过滤来自多个集合的输出
问题描述
假设我们有一个这样的脚本数组:
["xxxxx1","xxxxx2","xxxxx3","xxxxx4"]
我们在 db 中存在以下脚本集合:
Executed:{"_id" : ObjectId("xxx"),"scrip" : "xxxxx1" },{"_id" : ObjectId("xxy"),"scrip" : "xxxxx3" }......
In-process:{"_id" : ObjectId("xxx"),"scrip" : "xxxxx4" }, ....
Rejected:{"_id" : ObjectId("xxx"),"scrip" : "xxxxx5" }....
我们希望得到上述任何集合中都不存在的脚本数组。预期输出:
["xxxxx2"]
这如何在单个 mongodb 管道/查询中完成?
解决方案
以下查询可以为我们提供预期的输出:
db.executed.aggregate([
{
$group:{
"_id":null,
"executedScrips":{
$addToSet:"$scrip"
}
}
},
{
$lookup:{
"from":"inprocess",
"pipeline":[
{
$group:{
"_id":null,
"inprocessScrips":{
$addToSet:"$scrip"
}
}
}
],
"as":"inprocessLookup"
}
},
{
$lookup:{
"from":"rejected",
"pipeline":[
{
$group:{
"_id":null,
"rejectedScrips":{
$addToSet:"$scrip"
}
}
}
],
"as":"rejectedLookup"
}
},
{
$unwind:{
"path":"$inprocessLookup",
"preserveNullAndEmptyArrays":true
}
},
{
$unwind:{
"path":"$rejectedLookup",
"preserveNullAndEmptyArrays":true
}
},
{
$project:{
"scrips":{
$concatArrays:[
"$executedScrips",
{
$ifNull:["$inprocessLookup.inprocessScrips",[]]
},
{
$ifNull:["$rejectedLookup.rejectedScrips",[]]
}
]
}
}
},
{
$project:{
"_id":0,
"notFound":{
$setDifference:[["xxxxx1","xxxxx2","xxxxx3","xxxxx4"],"$scrips"]
}
}
}
]).pretty()
数据集:
收藏:executed
{ "_id" : ObjectId("5d60e572f00e0c8c3593b5ff"), "scrip" : "xxxxx1" }
{ "_id" : ObjectId("5d60e572f00e0c8c3593b600"), "scrip" : "xxxxx3" }
收藏:inprocess
{ "_id" : ObjectId("5d60f23ff00e0c8c3593b601"), "scrip" : "xxxxx4" }
收藏:rejected
{ "_id" : ObjectId("5d60f260f00e0c8c3593b602"), "scrip" : "xxxxx5" }
输出:
{ "notFound" : [ "xxxxx2" ] }
注意:如果集合中没有记录,则查询将失败,executed
因为聚合从那里开始。
更新 I:将传递请求数组而不是脚本数组
以下查询可以为我们提供预期的输出:
db.executed.aggregate([
{
$group:{
"_id":null,
"executedScrips":{
$addToSet:"$scrip"
}
}
},
{
$lookup:{
"from":"inprocess",
"pipeline":[
{
$group:{
"_id":null,
"inprocessScrips":{
$addToSet:"$scrip"
}
}
}
],
"as":"inprocessLookup"
}
},
{
$lookup:{
"from":"rejected",
"pipeline":[
{
$group:{
"_id":null,
"rejectedScrips":{
$addToSet:"$scrip"
}
}
}
],
"as":"rejectedLookup"
}
},
{
$unwind:{
"path":"$inprocessLookup",
"preserveNullAndEmptyArrays":true
}
},
{
$unwind:{
"path":"$rejectedLookup",
"preserveNullAndEmptyArrays":true
}
},
{
$project:{
"scrips":{
$concatArrays:[
"$executedScrips",
{
$ifNull:["$inprocessLookup.inprocessScrips",[]]
},
{
$ifNull:["$rejectedLookup.rejectedScrips",[]]
}
]
}
}
},
{
$addFields:{
"requests":[
{
"requestid" : "R1",
"stocks" : ["xxxxx1","xxxxx2","xxxxx3","xxxxx4"]
},
{
"requestid" : "R2",
"stocks" : ["xxxxx1","xxxxx3","xxxxx4"]
},
{
"requestid" : "R3",
"stocks" : ["xxxxx1","xxxxx3","xxxxx4","xxxxx10"]
}
]
}
},
{
$project:{
"_id":0,
"unmatchedRequests":{
$map:{
"input":"$requests",
"as":"request",
"in":{
$concat:{
$cond:[
{
$gt:[
{
$size:{
$setDifference:["$$request.stocks","$scrips"]
}
},
0
]
},
"$$request.requestid",
null
]
}
}
}
}
}
},
{
$project:{
"unmatchedRequests":{
$filter:{
"input":"$unmatchedRequests",
"as":"unmatchedRequest",
"cond":{
$ne:["$$unmatchedRequest",null]
}
}
}
}
}
]).pretty()
输出:
{ "unmatchedRequests" : [ "R1", "R3" ] }
注意:在第 7 个聚合阶段,我们正在注入请求数组。
推荐阅读
- flutter - 如何在颤动中实现“instagram 相机”滚动?
- java - 操作您是其公共对象的不同类的公共变量
- c - 在C中按字母顺序排序链表的问题
- unix - 在 awk 中使用 if-else 语句时的 OFS
- string - AppleScript - 我怎样才能让这个字符串正确通过?
- angular - PrimeNG 生产错误的 Angular 构建
- javascript - 访问包含字符的对象键:
- mongodb - Kubernetes 部署容器内的应用程序失败并出现错误 localhost:port 无法访问?
- maven - TestNg - 通过 mvn 命令行排除一个类(testrunner)
- python - 如何从python中的单个类继承一个类的多个实例