Conditional/max mongo 查询使用 spring mongo 模板
Conditional/max mongo queries using spring mongoTemplate
我在 mongodb 集合中有数百条这样的记录:
{
"city" : "London",
"eventTime": 1582866000,
"createdTime": 1582900145,
"eventDetails: {
...
}
}
这是对应的Event
class
public class Event {
private String city;
private long eventTime;
private long createdTime;
private EventDetails eventDetails;
//getters and setters
}
-eventTime
(所有时间值均为本地 epoch/unix 时间)将始终等于一个小时
-createdTime
被用作版本控制(大于 createdTime
,此信息的版本更新)
- 不使用 update/upsert 因为我有保留旧信息的用途
我希望能够查询这样的内容:
1) 给定版本时间戳 - return 每个 city
的对象列表(整个对象),每个 eventTime
,其中时间戳最接近(floor 或 celing)createdTime
2) 与 1) 相同,但对于 max(createdTime) - 对于每个 city
和每个 eventTime
基本上-每个city
,每个eventTime
都会有很多重复,因为有多个版本,我只想要我指定的版本,最新版本
我正在尝试使用 mongoTemplate in java (spring mongo) 进行这两个查询
我尝试过 Query
、Aggregation
、AggregationOperator.Max
但似乎没有任何效果
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(Criteria.where("city").is(city)),
Aggregation.match(Criteria.where("eventTime").gte(startTime).lte(endTime)),
Aggregation.group("$$ROOT").max("createdTime").as("createdTime")
);
AggregationResults<Event> groupResults = mongoTemplate.aggregate(aggregation, "collection-name", Event.class);
result = groupResults.getMappedResults();
我也试过在 mongodb shell 中进行这些查询,但也没有成功,它很相似,但不是 returning 我的对象结构想要
db.getCollection('collection-name').aggregate([{$group:{_id : "$$ROOT", createdTime : {$max:"$createdTime"}}}])
最大
db.collection.aggregate([
{
$group: {
_id: {
city: "$city",
eventTime: "$eventTime"
},
max: {
$max: "$createdTime"
},
data: {
$push: "$$ROOT"
}
}
},
{
$project: {
max_events: {
$filter: {
input: "$data",
cond: {
$eq: [
"$max",
"$$this.createdTime"
]
}
}
}
}
},
{
$unwind: "$max_events"
},
{
$replaceRoot: {
newRoot: "$max_events"
}
}
])
MongoTemplate
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
Aggregation agg = Aggregation.newAggregation(
group("city", "eventTime").max("createdTime").as("max").push("$$ROOT").as("data"),
project().and(new AggregationExpression() {
@Override
public Document toDocument(AggregationOperationContext context) {
return new Document("$filter",
new Document("input", "$data")
.append("cond", new Document("$eq", Arrays.asList("$max", "$$this.createdTime"))));
}
}).as("max_events"),
unwind("max_events"),
replaceRoot("max_events")
);
AggregationResults<Event> events = mongoTemplate.aggregate(agg, mongoTemplate.getCollectionName(Event.class), Event.class);
for(Event ev: events) {
System.out.println(ev);
}
最近
db.collection.aggregate([
{
$group: {
_id: {
city: "$city",
eventTime: "$eventTime"
},
data: {
$push: "$$ROOT"
}
}
},
{
$project: {
closest: {
$reduce: {
input: "$data",
initialValue: {
$arrayElemAt: [
"$data",
0
]
},
in: {
$cond: [
{
$lt: [
{
$abs: {
$subtract: [
"$$this.eventTime",
"$$this.createdTime"
]
}
},
{
$abs: {
$subtract: [
"$$value.eventTime",
"$$value.createdTime"
]
}
}
]
},
"$$this",
"$$value"
]
}
}
}
}
},
{
$unwind: "$closest"
},
{
$replaceRoot: {
newRoot: "$closest"
}
}
])
MongoTemplate
Aggregation agg = Aggregation.newAggregation(
group("city", "eventTime").push("$$ROOT").as("data"),
project().and(new AggregationExpression() {
@Override
public Document toDocument(AggregationOperationContext context) {
return new Document("$reduce",
new Document("input", "$data")
.append("initialValue", new Document("$arrayElemAt", Arrays.asList("$data", 0)))
.append("in", new Document("$cond", Arrays.asList(
new Document("$lt", Arrays.asList(
new Document("$abs", new Document("$subtract", Arrays.asList("$$this.eventTime", "$$this.createdTime"))),
new Document("$abs", new Document("$subtract", Arrays.asList("$$value.eventTime", "$$value.createdTime"))))),
"$$this",
"$$value"))));
}
}).as("closest"),
unwind("closest"),
replaceRoot("closest")
);
AggregationResults<Event> events = mongoTemplate.aggregate(agg, mongoTemplate.getCollectionName(Event.class), Event.class);
for(Event ev: events) {
System.out.println(ev);
}
我在 mongodb 集合中有数百条这样的记录:
{
"city" : "London",
"eventTime": 1582866000,
"createdTime": 1582900145,
"eventDetails: {
...
}
}
这是对应的Event
class
public class Event {
private String city;
private long eventTime;
private long createdTime;
private EventDetails eventDetails;
//getters and setters
}
-eventTime
(所有时间值均为本地 epoch/unix 时间)将始终等于一个小时
-createdTime
被用作版本控制(大于 createdTime
,此信息的版本更新)
- 不使用 update/upsert 因为我有保留旧信息的用途
我希望能够查询这样的内容:
1) 给定版本时间戳 - return 每个 city
的对象列表(整个对象),每个 eventTime
,其中时间戳最接近(floor 或 celing)createdTime
2) 与 1) 相同,但对于 max(createdTime) - 对于每个 city
和每个 eventTime
基本上-每个city
,每个eventTime
都会有很多重复,因为有多个版本,我只想要我指定的版本,最新版本
我正在尝试使用 mongoTemplate in java (spring mongo) 进行这两个查询
我尝试过 Query
、Aggregation
、AggregationOperator.Max
但似乎没有任何效果
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(Criteria.where("city").is(city)),
Aggregation.match(Criteria.where("eventTime").gte(startTime).lte(endTime)),
Aggregation.group("$$ROOT").max("createdTime").as("createdTime")
);
AggregationResults<Event> groupResults = mongoTemplate.aggregate(aggregation, "collection-name", Event.class);
result = groupResults.getMappedResults();
我也试过在 mongodb shell 中进行这些查询,但也没有成功,它很相似,但不是 returning 我的对象结构想要
db.getCollection('collection-name').aggregate([{$group:{_id : "$$ROOT", createdTime : {$max:"$createdTime"}}}])
最大
db.collection.aggregate([
{
$group: {
_id: {
city: "$city",
eventTime: "$eventTime"
},
max: {
$max: "$createdTime"
},
data: {
$push: "$$ROOT"
}
}
},
{
$project: {
max_events: {
$filter: {
input: "$data",
cond: {
$eq: [
"$max",
"$$this.createdTime"
]
}
}
}
}
},
{
$unwind: "$max_events"
},
{
$replaceRoot: {
newRoot: "$max_events"
}
}
])
MongoTemplate
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
Aggregation agg = Aggregation.newAggregation(
group("city", "eventTime").max("createdTime").as("max").push("$$ROOT").as("data"),
project().and(new AggregationExpression() {
@Override
public Document toDocument(AggregationOperationContext context) {
return new Document("$filter",
new Document("input", "$data")
.append("cond", new Document("$eq", Arrays.asList("$max", "$$this.createdTime"))));
}
}).as("max_events"),
unwind("max_events"),
replaceRoot("max_events")
);
AggregationResults<Event> events = mongoTemplate.aggregate(agg, mongoTemplate.getCollectionName(Event.class), Event.class);
for(Event ev: events) {
System.out.println(ev);
}
最近
db.collection.aggregate([
{
$group: {
_id: {
city: "$city",
eventTime: "$eventTime"
},
data: {
$push: "$$ROOT"
}
}
},
{
$project: {
closest: {
$reduce: {
input: "$data",
initialValue: {
$arrayElemAt: [
"$data",
0
]
},
in: {
$cond: [
{
$lt: [
{
$abs: {
$subtract: [
"$$this.eventTime",
"$$this.createdTime"
]
}
},
{
$abs: {
$subtract: [
"$$value.eventTime",
"$$value.createdTime"
]
}
}
]
},
"$$this",
"$$value"
]
}
}
}
}
},
{
$unwind: "$closest"
},
{
$replaceRoot: {
newRoot: "$closest"
}
}
])
MongoTemplate
Aggregation agg = Aggregation.newAggregation(
group("city", "eventTime").push("$$ROOT").as("data"),
project().and(new AggregationExpression() {
@Override
public Document toDocument(AggregationOperationContext context) {
return new Document("$reduce",
new Document("input", "$data")
.append("initialValue", new Document("$arrayElemAt", Arrays.asList("$data", 0)))
.append("in", new Document("$cond", Arrays.asList(
new Document("$lt", Arrays.asList(
new Document("$abs", new Document("$subtract", Arrays.asList("$$this.eventTime", "$$this.createdTime"))),
new Document("$abs", new Document("$subtract", Arrays.asList("$$value.eventTime", "$$value.createdTime"))))),
"$$this",
"$$value"))));
}
}).as("closest"),
unwind("closest"),
replaceRoot("closest")
);
AggregationResults<Event> events = mongoTemplate.aggregate(agg, mongoTemplate.getCollectionName(Event.class), Event.class);
for(Event ev: events) {
System.out.println(ev);
}