问题描述
这里是存储数据的示例
[
{
"userId":"user123","name":"John","card":{
"amount":1000.0,"sentMoneyList":[
{
"creationDate":"2019-08-07T00:00:00.000+0000","shopId":"merchant1","loyaltyPoint":200,"amount":250
},{
"creationDate":"2019-01-07T00:00:00.000+0000","shopId":"merchant2","loyaltyPoint":100,"amount":99
}
],"receivedMoneyList":[
{
"creationDate":"2019-09-07T00:00:00.000+0000","amount":40
},{
"creationDate":"2019-03-07T00:00:00.000+0000","amount":500
}
]
}
}
]
我想建立一个从给定日期开始的所有用户的收款和汇款时间表。
如果startDate为"2019-02-01T00:00:00.000+0000"
,则我的请求的输出应如下所示:
[
{
"userId":"user123","amount":250
}
]
}
},{
"userId":"user123","amount":40
}
]
}
},"receivedMoneyList":[
{
"creationDate":"2019-03-07T00:00:00.000+0000","amount":500
}
]
}
}
]
以下是尝试获得此结果的Java代码:
Criteria criteriaClient = new Criteria();
MatchOperation matchOperation = match(criteriaClient.orOperator(
Criteria.where("card.sentMoneyList.creationDate").gte(startDate),Criteria.where("card.receivedMoneyList.creationDate").gte(startDate)));
UnwindOperation unwindSent = Aggregation.unwind("card.sentMoneyList");
UnwindOperation unwindReceived = Aggregation.unwind("card.receivedMoneyList");
Aggregation aggregation = Aggregation.newAggregation(unwindSent,unwindReceived,matchOperation);
List<UserDTO> result = mongoTemplate.aggregate(
aggregation,"users",UserDTO.class).getMappedResults();
它给出一个空的列表。为了得到上面的结果,查询中缺少什么? 谢谢
解决方法
您可以使用$facet
获得预期的输出,这有助于您对传入的数据进行分类。在这里,我在 sentMoney 数组中获得了 sentMoneyList 数组,在 receivedMoney 中获得了 receivedMoneyList 数组。然后汇总任何能为您提供输出的内容。
public List<Object> test() {
Aggregation aggregation = Aggregation.newAggregation(
facet(
p -> new Document("$project",new Document("card.receivedMoneyList",0)
),a -> new Document("$addFields",new Document("card.sentMoneyList",new Document("$filter",new Document("input","$card.sentMoneyList")
.append("cond",new Document("$gte",Arrays.asList("$$this.creationDate","2019-02-01T00:00:00.000+0000"))
)
)
)
),unwind("$card.sentMoneyList")
).as("sentMoney").and(
p -> new Document("$project",new Document("card.receivedMoney","$card.receivedMoney")
.append("cond",unwind("$card.receivedMoney")
).as("receivedMoney"),p -> new Document("$project",new Document("combined",new Document("$concatArrays",Arrays.asList("$sentMoney","$receivedMoney"))
)
),unwind("$combined"),replaceRoot("combined")
).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());
return mongoTemplate.aggregate(aggregation,mongoTemplate.getCollectionName(Users.class),Object.class).getMappedResults();
}
首先,我要求您使用Object.class
来获取汇总结果并以List<Object>
的形式返回。如果效果良好,则可以将此模型转换为UserDTO.class
,其结构应与输出相同。
您已添加目标集合users
,但这不是一个好习惯。因此,请使用mongoTemplate.getCollectionName(YOUR_TARGET_COLLECTION.class)
否:我没有尝试过此代码,但这是基于有效的Mongo playground
编写的