首页 > 解决方案 > 集合上的差分操作

问题描述

我们有以下收藏:

要求:

    {  "requestid" : 'R1', "stocks" : [{"scripid" : "xxxxx1" }, {"scripid" : "xxxxx2" },{"scripid" : "xxxxx3" },{"scripid" : "xxxxx4" }] }
    {  "requestid" : 'R2', "stocks" : [{"scripid" : "xxxxx0" }] }

股票:

{"scripid" : "xxxxx2" }
{"scripid" : "xxxxx3" }
{"scripid" : "..." }

我们希望将请求的票据与股票收集进行比较 - 并返回不属于股票收集的一部分的请求(和票据)。
所以mongo操作的结果会是:

 {  "requestid" : 'R1', "stocks" : [{"scripid" : "xxxxx1" }, {"scripid" : "xxxxx4" }] }
 {  "requestid" : 'R2', "stocks" : [{"scripid" : "xxxxx0" }] }

如何以最有效的方式实现这一点。
我们正在使用 java 驱动程序 3.7.xxx

标签: mongodbmongodb-queryaggregation-framework

解决方案


我相信这可以解决问题:

db.requests.aggregate([{
    $lookup: {
        from: "stocks",
        localField: "stocks.scriptid",
        foreignField: "scriptid",
        as: "matched_stocks"
    }
}, {
    $project: {
        "matched_stocks._id": 0
    }
}, {
    $project: {
        request_id: 1,
        stocks: {
            $setDifference: ["$stocks", "$matched_stocks"]
        }
    }
}])

编辑:

正如下面@MrS.Sharma 所建议的,您可以Aggregates.project(Projections.computed("stocks", Document.parse("{ $setDifference: ['$stocks', '$matched_stocks'] }")))使用$setDifference.

编辑2:

我想这就是实际的完整答案:

AggregateIterable<Document> documents =
    requests.aggregate(
        Arrays.asList(
            Aggregates.lookup("stocks", "stocks.scrip", "scrip", "matched_stocks"),
            Aggregates.project(Projections.exclude("matched_stocks._id")),
            Aggregates.project(
                Projections.fields(
                    Projections.include("requestid"),
                    Projections.computed(
                        "stocks",
                        Document.parse(
                            "{ $setDifference: ['$stocks', '$matched_stocks'] }"))))));

推荐阅读