Java Spring MongoDB在天数差为x天时查询文档
我有一个包含两个日期字段的集合,我正在尝试查询所有相差15天的记录:Java Spring MongoDB在天数差为x天时查询文档,java,mongodb,spring-boot,criteria,spring-data-mongodb,Java,Mongodb,Spring Boot,Criteria,Spring Data Mongodb,我有一个包含两个日期字段的集合,我正在尝试查询所有相差15天的记录: { "_id" : "someid", "factoryNumber" : 123, "factoryName" : "some factory name", "visitType" : "audit", "personelId" : "somePersonel", "lastVisit": ISODate("2018-10-30T00:00:00.000+0000"), "accep
{
"_id" : "someid",
"factoryNumber" : 123,
"factoryName" : "some factory name",
"visitType" : "audit",
"personelId" : "somePersonel",
"lastVisit": ISODate("2018-10-30T00:00:00.000+0000"),
"acceptedDate" : ISODate("2018-11-16T00:00:00.000+0000")
}
现在,在某些情况下,acceptedDate
将不存在,因此我需要根据当前日期对其进行评估。不完全确定如何在spring中编写此类查询以获得所需的结果
Criteria.where("acceptedDate").
(is 15 days past last visit or current date if last visit not present)
您需要使用聚合管道来获取文档
-如果接受日期为null,则设置当前日期$ifNull
-将字段$addFields
、从
和从天
添加到现有文档中今天
- 过滤
$redact
-在字段和筛选器中匹配$redact
-排除在$project
阶段中添加的字段$addFields
db.t1.aggregate([
{$addFields : {
from : {$ifNull : ["$acceptedDate", new Date()]}
}},
{$addFields: {
fromDays : {$sum : [{$multiply : [365, {$year : "$from"}]}, {$dayOfYear : "$from"}]},
toDays : {$sum : [{$multiply : [365, {$year : "$lastVisit"}]}, {$dayOfYear : "$lastVisit"}]}
}},
{ $redact: {
$cond: {
if: {$lte : [{$subtract : ["$fromDays", "$toDays"]}, 15]},
then: "$$DESCEND",
else: "$$PRUNE"
}
}
},
{$project : {from:0, fromDays:0, toDays:0}}
])
样本采集
> db.t1.find().pretty()
{
"_id" : "someid",
"factoryNumber" : 123,
"factoryName" : "some factory name",
"visitType" : "audit",
"personelId" : "somePersonel",
"lastVisit" : ISODate("2018-10-30T00:00:00Z"),
"acceptedDate" : ISODate("2018-11-16T00:00:00Z")
}
{
"_id" : "someotherid",
"factoryNumber" : 123,
"factoryName" : "some factory name",
"visitType" : "audit",
"personelId" : "somePersonel",
"lastVisit" : ISODate("2018-10-30T00:00:00Z")
}
至少150天的结果
> db.t1.aggregate([ {$addFields : { from : {$ifNull : ["$acceptedDate", new Date()]} }}, {$addFields: { fromDays : {$sum : [{$multiply : [365, {$year : "$from"}]}, {$dayOfYear : "$from"}]}, toDays : {$sum : [{$multiply : [365, {$year : "$lastVisit"}]}, {$dayOfYear : "$lastVisit"}]} }}, { $redact: { $cond: { if: {$lte : [{$subtract : ["$fromDays", "$toDays"]}, 150]}, then: "$$DESCEND", else: "$$PRUNE" } } }, {$project : {from:0, fromDays:0, toDays:0}} ]).pretty()
{
"_id" : "someid",
"factoryNumber" : 123,
"factoryName" : "some factory name",
"visitType" : "audit",
"personelId" : "somePersonel",
"lastVisit" : ISODate("2018-10-30T00:00:00Z"),
"acceptedDate" : ISODate("2018-11-16T00:00:00Z")
}
{
"_id" : "someotherid",
"factoryNumber" : 123,
"factoryName" : "some factory name",
"visitType" : "audit",
"personelId" : "somePersonel",
"lastVisit" : ISODate("2018-10-30T00:00:00Z")
}
>
将mongo聚合查询转换为spring mongodb查询从3.6开始,您必须使用新的运算符
$expr
,它允许在匹配查询或常规查询中使用聚合表达式
您可以创建json查询并直接传递它,因为在常规查询中spring还不支持json查询
15天=15*24*60*60*1000=1296000000毫秒
Query query = new BasicQuery("{'$expr':{'$gte':[{'$subtract':[{'$ifNull':['$acceptedDate',{'$date':" + System.currentTimeMillis() + "}]},'$lastVisit']},1296000000]}}");
List<Document> results = mongoTemplate.find(query, Document.class);
3.2版本
AggregationOperation redact = new AggregationOperation() {
@Override
public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("if", BasicDBObject.parse("{'$gte':[{'$subtract':[{'$ifNull':['$acceptedDate', {'$date':" + System.currentTimeMillis() + "}]},'$lastVisit']},1296000000]}}"));
map.put("then", "$$KEEP");
map.put("else", "$$PRUNE");
return new BasicDBObject("$redact", new BasicDBObject("$cond", map));
};
Aggregation aggregation = Aggregation.newAggregation(redact);
List<FactoryAcceptance> results = mongoTemplate.aggregate(aggregation, FactoryAcceptance.class, FactoryAcceptance.class).getMappedResults();
AggregationOperation编校=新的AggregationOperation(){
@凌驾
公共数据库对象toDBObject(聚合操作上下文聚合操作上下文){
Map Map=newlinkedhashmap();
map.put(“if”,BasicDBObject.parse(“{'$gte':[{'$subtract':[{'$ifNull':['$acceptedDate',{'$date':“+System.currentTimeMillis()+”}]},$lastVisit']},1296000000]}”);
map.put(“then”,“$$KEEP”);
map.put(“else”,“$$PRUNE”);
返回新的BasicDBObject($redact),新的BasicDBObject($cond,map));
};
聚合=聚合。新建聚合(修订);
List results=mongoTemplate.aggregate(聚合,FactoryAcceptance.class,FactoryAcceptance.class).getMappedResults();
nice,我最关心的是spring部分,因为它会产生这个问题+公司范围内目前使用的版本是3.2。我想我不能使用expralso当我重写聚合操作时,它强迫我使用DBObject?与我的集合实体名称相反?更新了3.2版和spring mongo 1.x jar的答案。感谢您提出的一个快速问题,如果我的实体名为FactoryAcceptance,那么我需要将列表映射到我的列表?它会在记录中包含所有字段吗?由于某种原因,我在第一个map.put-basicdbobobject.parse上遇到了一个json解析错误,但对我来说很好
AggregationOperation redact = new AggregationOperation() {
@Override
public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("if", BasicDBObject.parse("{'$gte':[{'$subtract':[{'$ifNull':['$acceptedDate', {'$date':" + System.currentTimeMillis() + "}]},'$lastVisit']},1296000000]}}"));
map.put("then", "$$KEEP");
map.put("else", "$$PRUNE");
return new BasicDBObject("$redact", new BasicDBObject("$cond", map));
};
Aggregation aggregation = Aggregation.newAggregation(redact);
List<FactoryAcceptance> results = mongoTemplate.aggregate(aggregation, FactoryAcceptance.class, FactoryAcceptance.class).getMappedResults();