Spring数据mongodb模拟ifNull行为

时间:2016-04-06 14:38:50

标签: java spring mongodb aggregation-framework spring-data-mongodb

我有一系列表格:

{ "_id" : { "$oid" : "57050f22d5f79d2e6866c6f8" }, "form_name" : "Form 1", "ver" : 0, "createdAt" : { "$date" : 1459950030037 } }
{ "_id" : { "$oid" : "57050fa6d5f79d2e6866c6f9" }, "form_name" : "Form 1", "ver" : 1, "vid" : { "$oid" : "57050f22d5f79d2e6866c6f8" }, "createdAt" : { "$date" : 1459950030037 } }
{ "_id" : { "$oid" : "57050ff2d5f79d2e6866c6fa" }, "form_name" : "Form 1", "ver" : 2, "vid" : { "$oid" : "57050f22d5f79d2e6866c6f8" }, "createdAt" : { "$date" : 1459950030037 } }
{ "_id" : { "$oid" : "570511ced5f79d2e6866c6fb" }, "form_name" : "Form 2", "ver" : 0, "createdAt" : { "$date" : 1459950030037 } }

我的版本化表格如下:

db.forms.aggregate([
    {"$match":{"deletedAt":{"$exists":false}}},
    {"$sort":{"createdAt":1}},
    {"$group":{
            "_id": {"$ifNull":["$vid", "$_id"]},
            "vid":{"$push":"$$ROOT"}
        }
    }
])

我得到了这样的JSON答案:

[
    {
        "_id" : ObjectId("57050f22d5f79d2e6866c6f8"),
        "vid" : [
            {
                "_id" : ObjectId("57050f22d5f79d2e6866c6f8"),
                "form_name" : "Form 1",
                "ver" : 0,
                "createdAt" : ISODate("2016-04-06T13:29:06.079Z")
            },
            {
                "_id" : ObjectId("57050fa6d5f79d2e6866c6f9"),
                "form_name" : "Form 1",
                "ver" : 1,
                "createdAt" : ISODate("2016-04-06T13:31:18.742Z"),
                "vid" : ObjectId("57050f22d5f79d2e6866c6f8")
            },
            {
                "_id" : ObjectId("57050ff2d5f79d2e6866c6fa"),
                "form_name" : "Form 1",
                "ver" : 2,
                "createdAt" : ISODate("2016-04-06T13:32:34.986Z"),
                "vid" : ObjectId("57050f22d5f79d2e6866c6f8")
            }
        ]
    },
    {
        "_id" : ObjectId("570511ced5f79d2e6866c6fb"),
        "vid" : [
            {
                "_id" : ObjectId("570511ced5f79d2e6866c6fb"),
                "form_name" : "Form 2",
                "ver" : 0,
                "createdAt" : ISODate("2016-04-06T13:40:30.037Z")
            }
        ]
    }
]

在我的Java后端,我按照以下方式执行:

List<DBObject> tmpAggr = new ArrayList<>();
tmpAggr.add(new BasicDBObject("$match", new BasicDBObject("deletedAt", new BasicDBObject("$exists", false))));
tmpAggr.add(new BasicDBObject("$sort",  new BasicDBObject("createdAt", 1)));
tmpAggr.add(new BasicDBObject("$group", BasicDBObjectBuilder.start("_id", new BasicDBObject("$ifNull", new String[]{"$vid", "$_id"}))
                                                        .append("vid", new BasicDBObject("$push", "$$ROOT")).get()));
tmpAggr.add(new BasicDBObject("$sort",  new BasicDBObject("_id", 1)));
        list_with_versions = Collections.unmodifiableList(tmpAggr);  
org.getDB().getCollection("forms").aggregate(list_with_versions).results()

如何使用Spring Data MongoDB框架重现此行为? 问题是没有ifNull构造。如何管理这个问题?

1 个答案:

答案 0 :(得分:1)

您可以创建一个实施 AggregationOperation 接口的变通方法,以接收DBObject代表 {{1的聚合管道中的单个操作}} 运营商:

$ifNull

然后在聚合管道中将public class GroupAggregationOperation implements AggregationOperation { private DBObject operation; public GroupAggregationOperation (DBObject operation) { this.operation = operation; } @Override public DBObject toDBObject(AggregationOperationContext context) { return context.getMappedObject(operation); } } 操作实现为DBObject,该操作与您拥有的操作相同:

$group

然后您可以将其用作:

DBObject operation = (DBObject) new BasicDBObject(
    "$group", BasicDBObjectBuilder.start(
        "_id", new BasicDBObject(
            "$ifNull", new String[]{"$vid", "$_id"}
        )
    )
    .append("vid", new BasicDBObject("$push", "$$ROOT"))
    .get()              
);