Spring Data MongoDB应用程序设计和数据聚合 [英] Spring data mongodb application design and data aggregation
问题描述
我正在使用 spring data mongo 和 angularjs . 这是模型:
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;
}
我没有嵌入付款模型,因为我需要它具有一个ID并以其自己的形式对其进行编辑. 在应用程序的主页上,它表示按月付款的租赁清单.在列表上方的选择中选择年份.
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.
如何更好地按月使用其余付款来更好地分配租赁:可能是先进行租赁,然后将ID注入付款,还是有更好的解决方案?目前,我选择使用聚合:
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();
问题是匹配在这里是排他性的,例如,如果2017年没有付款,则租赁清单为空.我在mongo中看到"addFields"功能,该功能尚未在Spring数据mongodb中实现.对我来说,更好的json返回值是:
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.
如何通过spring数据mongodb获得此信息?
How can I obtain this with spring data mongodb?
任何帮助将不胜感激!
推荐答案
每当Spring Data Mongo缺少您需要的AggregationOperation(重现$addFields
,$redact
...)时,就有一种解决方法(有些人可能说它又脏又快)解决方案)是直接使用com.mongodb.client工具将原始聚合传递给Spring:
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()作为List<Document>
传递到聚合管道(实际上,如上面建议的那样,使用Document.parse()以List<? extends Bson>
的原始形式传递),您当然也可以使用new Document()
使其外观更像是适当的OOP代码.当原始聚合很复杂,或者由于嵌套文档的许多嵌套组件对我来说太冗长时,我倾向于使用原始形式.
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.
这篇关于Spring Data MongoDB应用程序设计和数据聚合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!