1

我的窗體的集合:春數據MongoDB的模擬IFNULL行爲

{ "_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

你可以創建一個實現AggregationOperation接口取一個DBObject表示與$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); 
    } 
} 

然後實現$group操作彙總管道中的DBObject與您擁有的相同:

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

然後您可以使用它:

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; 

GroupAggregationOperation groupOp = new GroupAggregationOperation(operation); 
Aggregation agg = newAggregation(
    match(Criteria.where("deletedAt").exists(false)), 
    sort(ASC, "deletedAt"), 
    groupOp 
); 
AggregationResults<Forms> results = mongoTemplate.aggregate(agg, Forms.class); 
List<Forms> forms = results.getMappedResults(); 
+1

工程就像一個魅力。謝謝 – mor