Spring 引导和 MongoDB 未知运算符:$last

Spring Boot and MongoDB unknown operator: $last

我正在尝试使用 $group:

执行最简单的聚合操作
{ "_id" : "$sensor", "lastTimestamp" : { "$last" : "$timestamp"}}

示例记录如下:

sensor: A
timestamp: 3:27:14
value: 3.29

sensor: A
timestamp: 4:27:14
value: 5.29

如果我在 MongoDB Compass 中执行查询,那么它 returns 有效结果:

_id: "A"
lastTimestamp: 4:27:14

如果我将其作为 Spring Data Reposirory 的自定义查询来执行,例如

public interface EventDataProvider extends MongoRepository<Event, String> {

    @Query("{ \"_id\" : \"$sensor\", \"lastTimestamp\" : { \"$last\" : \"$timestamp\"}}")
    List<Object> customQuery();
}

然后我得到异常:

com.mongodb.MongoQueryException: Query failed with error code 2 and error message 'unknown operator: $last' on server localhost:27017
    at com.mongodb.operation.FindOperation.call(FindOperation.java:735) ~[mongodb-driver-core-3.11.2.jar:na]
    at com.mongodb.operation.FindOperation.call(FindOperation.java:725) ~[mongodb-driver-core-3.11.2.jar:na]
    at com.mongodb.operation.OperationHelper.withReadConnectionSource(OperationHelper.java:463) ~[mongodb-driver-core-3.11.2.jar:na]

你能告诉我如何使自定义查询工作吗?

谢谢

要使用 Spring 存储库对象 运行 聚合组查询,您必须使用 @Aggregation 而不是 @Query

从 Spring 引导应用程序定义存储库和 运行:

@Repository
public interface SensorRepository extends MongoReppsitory<Sensor, String> {

    @Aggregation("{ $group : { _id : $sensor, lastTimestamp: { $last : $timestamp } } }")
    List<SensorAggregate> groupBySensors();
}

运行 sensor 集合上的聚合:

@Autowired
private SensorRepository repos;
// ...
public void run(String... strings) throws Exception {
    List<SensorAggregate> list = repos.groupBySensors();
    list.forEach(System.out::println);
}

POJO 类 SensorSensorAggregate:

public class Sensor {

    private String id;
    private String sensor;
    private String timestamp;
    private double value;

    public Sensor(String id, String sensor, String timestamp, double value) {
        this.id = id;
        this.sensor = sensor;
        this.timestamp = timestamp;
        this.value = value;
    }

    public String getId() {
        return id;
    }

     public String getSensor() {
         return sensor;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return sensor + ", " + timestamp;
    }
} 


public class SensorAggregate {

    private @Id String sensor;                                                     
    private String lastTimestamp;

    public PersonAggregate(String sensor, String lastTimestamp) {
        this.sensor = sensor;
        this.lastTimestamp = lastTimestamp;
    }

     public String getSensor() {
         return sensor;
    }

    public String getLastTimestamp() {
        return lastTimestamp;
    }

    @Override
    public String toString() {
        return sensor + ", " + lastTimestamp;
    }
}