过滤来自多个 collections 的输出
Filter output from multiple collections
假设我们有这样一组纸条:
["xxxxx1","xxxxx2","xxxxx3","xxxxx4"]
我们在数据库中存在以下 collections 个脚本:
Executed:{"_id" : ObjectId("xxx"),"scrip" : "xxxxx1" },{"_id" : ObjectId("xxy"),"scrip" : "xxxxx3" }......
In-process:{"_id" : ObjectId("xxx"),"scrip" : "xxxxx4" }, ....
Rejected:{"_id" : ObjectId("xxx"),"scrip" : "xxxxx5" }....
我们希望获得上述 collections 中不存在的一组凭证。
预期输出:
["xxxxx2"]
如何在单个 mongodb pipeline/query 中完成?
以下查询可以获得预期的输出:
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()
数据集:
Collection: executed
{ "_id" : ObjectId("5d60e572f00e0c8c3593b5ff"), "scrip" : "xxxxx1" }
{ "_id" : ObjectId("5d60e572f00e0c8c3593b600"), "scrip" : "xxxxx3" }
Collection: inprocess
{ "_id" : ObjectId("5d60f23ff00e0c8c3593b601"), "scrip" : "xxxxx4" }
Collection: rejected
{ "_id" : ObjectId("5d60f260f00e0c8c3593b602"), "scrip" : "xxxxx5" }
输出:
{ "notFound" : [ "xxxxx2" ] }
注意:如果executed
collection中没有记录,查询将失败,因为聚合从那里开始。
更新 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个聚合阶段,我们正在注入请求数组。
假设我们有这样一组纸条:
["xxxxx1","xxxxx2","xxxxx3","xxxxx4"]
我们在数据库中存在以下 collections 个脚本:
Executed:{"_id" : ObjectId("xxx"),"scrip" : "xxxxx1" },{"_id" : ObjectId("xxy"),"scrip" : "xxxxx3" }......
In-process:{"_id" : ObjectId("xxx"),"scrip" : "xxxxx4" }, ....
Rejected:{"_id" : ObjectId("xxx"),"scrip" : "xxxxx5" }....
我们希望获得上述 collections 中不存在的一组凭证。 预期输出:
["xxxxx2"]
如何在单个 mongodb pipeline/query 中完成?
以下查询可以获得预期的输出:
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()
数据集:
Collection: executed
{ "_id" : ObjectId("5d60e572f00e0c8c3593b5ff"), "scrip" : "xxxxx1" }
{ "_id" : ObjectId("5d60e572f00e0c8c3593b600"), "scrip" : "xxxxx3" }
Collection: inprocess
{ "_id" : ObjectId("5d60f23ff00e0c8c3593b601"), "scrip" : "xxxxx4" }
Collection: rejected
{ "_id" : ObjectId("5d60f260f00e0c8c3593b602"), "scrip" : "xxxxx5" }
输出:
{ "notFound" : [ "xxxxx2" ] }
注意:如果executed
collection中没有记录,查询将失败,因为聚合从那里开始。
更新 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个聚合阶段,我们正在注入请求数组。