Spring data mongodb application design and data aggregation

…衆ロ難τιáo~ 提交于 2019-12-23 05:25:07

问题


I was developing a little application with spring data mongo and angularjs. Here is model :

public class Lease {
        @Id
        private String id;
        private long created;
        private Lessor lessor;
        private Lessee lessee;
      }

public class Payment {
        @Id
        private String id;
        private Integer month;
        private Integer year;
        private Long amount;
        private String leaseId;
     }

I did not embed Payment model as I need it to have an id and edit it in its own form. On the main page of the app it represents a list of leases with payments by month. The year is chosen in a select above the list.

How to better load leases with payments by year by month using rest: may be first load leases then inject ids to payments or there is a better solution? For the moment I chose to use aggregation:

LookupOperation lookupOperation = LookupOperation.newLookup().
                                  from("payment").
                                  localField("leaseId").
                                  foreignField("id").
                                  as("payments");

AggregationOperation match = Aggregation.match(Criteria.where("payments.year").is(year));
Aggregation aggregation = Aggregation.newAggregation(lookupOperation, match);

return mongoOperations.aggregate(aggregation, "lease", LeaseAggregation.class).getMappedResults();

The problem is that match is exclusive here and for example if there are no payments in 2017, list of leases is empty. I saw "addFields" functionality in mongo by it is not yet implemented in spring data mongodb. A better json return for me would be :

{"leases" : [{"id" : 123, "created" : 12324343434, "payments" : [123, 455, 343, 323, 344, null, null, 332, 323, 232, 333, 434}]}

where payments will represent twelve months of a particular year.

How can I obtain this with spring data mongodb?

Any help would be appreciated!


回答1:


Whenever Spring Data Mongo lacks an AggregationOperation you need (to reproduce $addFields, $redact...), a workaround (some may say quick and dirty solution) is to pass the raw aggregation to Spring, using directly the com.mongodb.client tools :

String collectionName = mongoTemplate.getCollectionName(Payment.class);
MongoCollection<Document> collection = mongoClient.getDatabase(mongoTemplate.getDb().getName()).getCollection(collectionName);

AggregateIterable<Document> ai = collection.aggregate(Arrays.asList(
    Document.parse(/* { "group" : { ... } } */)))

MongoCollection.aggregate() is passed the aggregation pipeline as List<Document> (in fact List<? extends Bson> in raw form as suggested above using Document.parse(), and you can of course also use new Document() to make it look more like proper OOP code. I tend to use the raw form when the raw aggregation is complex or as many nested components for nested Document are too much verbose for me, but that's a matter of taste.



来源:https://stackoverflow.com/questions/47616813/spring-data-mongodb-application-design-and-data-aggregation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!