Mongodb 在另一个集合中查找具有值的键

Mongodb 在另一个集合中查找具有值的键,mongodb,mongodb-query,aggregation-framework,mongodb-3.6.4,Mongodb,Mongodb Query,Aggregation Framework,Mongodb 3.6.4,我们有一个请求集合,示例文档如下: { "_id" : ObjectId("xxxxxx"), "requestId" : "REQ4", "scrip" : "5647" } { "_id" : ObjectId("xxxxxx"), "requestId" : "REQ4", "scrip" : "5648" } { "_id" : ObjectId("xxxxxx"), "requestId" : "REQ1", "s

我们有一个请求集合,示例文档如下:

{
    "_id" : ObjectId("xxxxxx"),
    "requestId" : "REQ4",
    "scrip" : "5647"
}
{
    "_id" : ObjectId("xxxxxx"),
    "requestId" : "REQ4",
    "scrip" : "5648"
}
{
    "_id" : ObjectId("xxxxxx"),
    "requestId" : "REQ1",
    "scrip" : "0001"
}
{
    "_id" : ObjectId("xxxxxx"),
    "requestId" : "REQ1",
    "scrip" : "0456"
}
纸条收集:

{
    "_id" : ObjectId("xxxx"),
    "scrip" : "0001"
}
{
    "_id" : ObjectId("xxxx"),
    "scrip" : "0456"
}
{
    "_id" : ObjectId("xxxx"),
    "scrip" : "5647"
}
我们需要返回在Scrips集合中包含所有相应Scrips的请求

预期输出:

{"_id" : ObjectId("xxxxxx"),
    "requestId" : "REQ1",
    "scrip" : ["0001","0456"]
}
我们如何做到这一点?

试试这个:

db.requests.aggregate([
    /** Filter to reduce dataset */
    { $match: { requestId: { $in: ['REQ4', 'REQ1', 'REQ5'] } } },
    /** check for matching docs based on scrip */
    {
        $lookup:
        {
            from: "scrips",
            localField: "scrip",
            foreignField: "scrip",
            as: "scrips"
        }
    }, { $addFields: { scrips: { $arrayElemAt: ['$scrips', 0] } } },
    /** Group all docs in request collection based on requestId */
    { $group: { _id: '$requestId', scrip: { $push: '$scrip' }, scrips: { $push: '$scrips' } } },
    /** Remove request docs if all request docs doesn't have match in scrips */
    { $match: { $expr: { $eq: [{ $size: '$scrip' }, { $size: '$scrips' }] } } },
    /** Transform final result */
    { $project: { _id: 0, requestId: '$_id', scrip: 1 } }
])
测试:

尝试以下方法:

db.requests.aggregate([
    /** Filter to reduce dataset */
    { $match: { requestId: { $in: ['REQ4', 'REQ1', 'REQ5'] } } },
    /** check for matching docs based on scrip */
    {
        $lookup:
        {
            from: "scrips",
            localField: "scrip",
            foreignField: "scrip",
            as: "scrips"
        }
    }, { $addFields: { scrips: { $arrayElemAt: ['$scrips', 0] } } },
    /** Group all docs in request collection based on requestId */
    { $group: { _id: '$requestId', scrip: { $push: '$scrip' }, scrips: { $push: '$scrips' } } },
    /** Remove request docs if all request docs doesn't have match in scrips */
    { $match: { $expr: { $eq: [{ $size: '$scrip' }, { $size: '$scrips' }] } } },
    /** Transform final result */
    { $project: { _id: 0, requestId: '$_id', scrip: 1 } }
])


测试:

我不明白你的问题,你说的子集是什么意思?您是如何获得
[“0001”,“0456”]
?REQ1在任务集合中有两个条目-分别有0001和0456的纸条我在请求集合中只看到一个
REQ1
,这是一个编辑错误。感谢您指出您想要检查请求集合
scrip
是否存在于纸条集合中&如果存在,请将它们推到一个数组中,如果不是,我不明白你的问题,你说的子集是什么意思?您是如何获得
[“0001”,“0456”]
?REQ1在任务集合中有两个条目-分别有0001和0456的纸条我在请求集合中只看到一个
REQ1
,这是一个编辑错误。感谢您指出您想要检查请求集合
scrip
是否存在于纸条集合中&如果存在,请将它们推到一个数组中,如果不是否?谢谢。但是,这将扫描整个请求和脚本集合(~1M条记录)。如果我仅为作为输入传入的请求的分块列表触发此操作,会发生什么情况。@IUnknown:可能有关系,也可能没有关系,但是的,我始终建议将数据集尽可能低,你的输入是什么样的?基本上使用一个
$match
stage它可能是一个数组['REQ4','REQ1'…]来限制每次扫描iteration@IUnknown:然后您可以将其添加为第一阶段::
{$match:{requestId:{$in:['REQ4','REQ1'…]}
Yes-但这将返回甚至部分匹配的请求,例如REQ4…而不是像REQ1Thanks这样的完全匹配候选。但是,这将扫描整个请求和脚本集合(~1M条记录)。如果我仅为作为输入传入的请求的分块列表触发此操作,这是怎么发生的。@IUnknown:可能有关系,也可能没有关系,但是的,这是正确的,我总是建议将您的数据集保持尽可能低,您的输入会是什么样子?基本上使用一个
$match
stage它可能是一个数组['REQ4','REQ1'…]来限制每次扫描iteration@IUnknown:然后您可以将其添加为第一阶段::
{$match:{requestId:{$in:['REQ4','REQ1'…]}
是-但这将返回部分匹配的请求,例如REQ4…而不是像REQ1这样的完全匹配候选