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 Framework 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

Смежные вопросы