Недействительный запрос при использовании QueryDSL с MongoDB

Я нашел сценарий, в котором запрос, созданный при использовании QueryDSL, не работает с mongodb, но работает с jpa. Код является частью проекта на github.

Метод находится в https://github.com/corneil/spring-data-demo/blob/master/src/main/java/org/springframework/data/demo/service/LocationAndDeviceServiceImpl.java

Код:

private List<LocationUpdate> findLocationsFunctions(String deviceId, Date startDate, Date endDate) {
    logger.info("findLocations:" + deviceId + "," + startDate + "," + endDate);
    DeviceInfo device = deviceInfoRepository.findByDeviceId(deviceId);
    if (device == null) {
        throw new DataRetrievalFailureException("DeviceInfo:" + deviceId);
    }
    return locationUpdateRepository.findByDeviceAndLocTimeBetween(device, startDate, endDate);
}
private List<LocationUpdate> findLocationsQsl(String deviceId, Date startDate, Date endDate) {
    logger.info("findLocations:" + deviceId + "," + startDate + "," + endDate);
    DeviceInfo device = deviceInfoRepository.findByDeviceId(deviceId);
    if (device == null) {
        throw new DataRetrievalFailureException("DeviceInfo:" + deviceId);
    }
    List<LocationUpdate> result = new ArrayList<LocationUpdate>();
    Iterable<LocationUpdate> resultSet = locationUpdateRepository
            .findAll(locationUpdate.device.eq(device).and(locationUpdate.locTime.between(startDate, endDate)));
    for (LocationUpdate loc : resultSet) {
        result.add(loc);
    }
    return result;
}
public List<LocationUpdate> findLocations(String deviceId, Date startDate, Date endDate) {
    return findLocationsFunctions(deviceId, startDate, endDate);
    // return findLocationsQsl(deviceId, startDate, endDate);
}

Комментируя findLocationsFunctions и раскомментировав findLocationsQsl, вы сможете вызвать проблему. Обычные тесты в проекте будут выполнять код JPA с использованием встроенного H2. Вам понадобится доступ к mondodb для выполнения тестов для профиля mongo. Файл database.properties содержит URL-адрес mongodb. Код:

./gradlew test testMongo

Думаю, проблема в том, как предикат QueryDSL конвертируется в Mongo Query. Когда я изначально делал mongoTemplate. Код:

List<LocationUpdate> locations = mongoTemplate .find(
   query(where("device").is(device).and("locTime").gte(startDate)
   .and("locTime").lte(endTime)), LocationUpdate.class);

было выдано исключение «Из-за ограничений BasicDBObject вы не можете добавить второй $ And» и пришлось изменить на:

Код:

List<LocationUpdate> locations = mongoTemplate .find(
   query(where("device").is(device).andOperator(
       where("locTime").gte(startDate),
      where("locTime").lte(endTime))), LocationUpdate.class);

Я заметил, что при использовании метода поиска отображается следующее:

Код:

"locTime" : { 
    "$gt" : { "$date" : "2014-04-02T14:06:23.600Z"} , 
    "$lt" : { "$date" : "2014-04-02T14:06:23.931Z"}
}

Код в findLocationsQsl не отображает никаких критериев, связанных с locTime.

Тестирование с помощью Spring Data MongoDB 1.5.0 и QueryDSL 3.3.4


person Corneil du Plessis    schedule 24.06.2014    source источник
comment
Что вы имеете в виду, говоря, что не отображает никаких критериев, связанных с locTime? Вы отлаживали вызовы Java-драйвера Mongo? Как сериализованный запрос выглядит в случае Querydsl?   -  person Timo Westkämper    schedule 28.06.2014
comment
Запросы регистрируются следующим образом: Использование Spring Data Repository findByDeviceAndLocTimeBetween поиск с использованием запроса: {device: {$ ref: deviceInfo, $ id: {$ oid: 53aead0e44aed74aa839299a}}, locTime: {$ gt: {$ date: 2014-06- 28T11: 54: 54.910Z}, $ lt: {$ date: 2014-06-28T11: 54: 55.142Z}}} Использование findAll (locationUpdate.device.eq (device) .and (locationUpdate.locTime.between (startDate, endDate))) findOne с помощью запроса: {deviceId: 1234-4567-6789}   -  person Corneil du Plessis    schedule 28.06.2014


Ответы (1)


Как также ответили в трекере проблем Querydsl, это похоже на проблему в интеграции Querydsl с Spring Data Mongodb. Похоже, что Spring Data сериализует даты иначе, чем сериализация даты Mongodb Java API по умолчанию.

person Timo Westkämper    schedule 26.06.2014
comment
Критерии даты вообще не отображаются. - person Corneil du Plessis; 26.06.2014