Spring Boot и MongoDB неизвестный оператор: $ last - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь выполнить простейшую операцию агрегирования, возможную с $ 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, то он возвращает действительный результат:

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

Если я выполню его как пользовательский запрос для репозитория данных Spring, например,

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$1.call(FindOperation.java:735) ~[mongodb-driver-core-3.11.2.jar:na]
    at com.mongodb.operation.FindOperation$1.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]

Не могли бы вы посоветовать, как заставить работать пользовательский запрос?

Спасибо

1 Ответ

0 голосов
/ 07 апреля 2020

Чтобы выполнить запрос группы агрегации с помощью объекта репозитория Spring, необходимо использовать @ Aggregation вместо @Query.

Определить репозиторий и запустить из Spring Boot application:

@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 Sensor и SensorAggregate:

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;
    }
}
...