Spring Data MongoDB, Поиск по длинному значению - PullRequest
0 голосов
/ 28 февраля 2020

У меня есть объект, хранящийся в mon go, который выглядит следующим образом (вот как он отображается в RoboMon go, когда я просматриваю документ):

{
    "_id": ObjectId("5e579c8674f69d1c1451f3ae"),
    ...
    "timestamp": NumberLong(1582800002779),
    ...
    "_class": "regular"
}

Объект, который я храню определяется следующим образом:

public class MyObjectModel {
    @Id
    @Field(value = ID_FIELD_NAME)
    private String id;
    @Field(value = TIMESTAMP_FIELD_NAME)
    private Long timestamp;
...
}

Мое намерение - получить список объектов в пределах таймфрейма. Вот как я создаю запрос с пружинными данными mon go db:

    public List<Criteria> generateAllCriteria() {
        List<Criteria> criteriaList = new ArrayList<>();
        Optional.ofNullable(searchCriteria.getFromTimestamp()).map(ts -> criteriaList.add(generateFromTimestampCriteria(ts)));
        Optional.ofNullable(searchCriteria.getToTimestamp()).map(ts -> criteriaList.add(generateToTimestampCriteria(ts)));
        return criteriaList;
    }

    private Criteria generateFromTimestampCriteria(Long fromTimestamp) {
        Criteria critFromTimestamp = Criteria.where(TIMESTAMP_FIELD_NAME).gte(fromTimestamp);
        log.debug("From Timestamp criteria {}", critFromTimestamp.getCriteriaObject().toJson());
        return critFromTimestamp;
    }

    private Criteria generateToTimestampCriteria(Long toTimestamp) {
        Criteria critToTimestamp = Criteria.where(TIMESTAMP_FIELD_NAME).lt(toTimestamp);
        log.debug("To Timestamp criteria {}", critToTimestamp.getCriteriaObject().toJson());
        return critToTimestamp;
    }
...
    List<Criteria> criteriaList = generateAllCriteria();

    Criteria finalCriteria = new Criteria();
    finalCriteria = finalCriteria.andOperator(criteriaList.toArray(new Criteria[criteriaList.size()]));
    log.debug("Final criteria {}", finalCriteria);
    Query query = new Query();
    query.addCriteria(finalCriteria);

    List<MyObjectModel> myObjects = mongoTemplate.find(query, MyObjectModel.class);

Запросы, когда я их отображаю, следующие:

From Timestamp criteria { "timestamp" : { "$gte" : { "$numberLong" : "1582714365857" } } }
To Timestamp criteria { "timestamp" : { "$lt" : { "$numberLong" : "1582887165858" } } }

И кажется, что окончательный критерий запроса чтобы быть таким:

o.s.data.mongodb.core.MongoTemplate - find using query: { "$and" : [{ "timestamp" : { "$gte" : { "$numberLong" : "1582714365857" } } }, { "timestamp" : { "$lt" : { "$numberLong" : "1582887165858" } } }] } fields: Document{{}} for class: class mypackage.model.MyObjectModel in collection: myObjectModel

На первый взгляд кажется, что все в порядке, но когда я запускаю его с Mon go вручную, он не возвращает никаких записей, что, на мой взгляд, означает, что это как-то неверно. Вот что именно я запускаю на Mon go:

db.getCollection('my-collection').find({ "$and" : [{ "timestamp" : { "$gte" : { "$numberLong" : "1582707873806" } } }, { "timestamp" : { "$lt" : { "$numberLong" : "1582887165858" } } }] })

И, очевидно, он не возвращает никаких записей. Но когда я изменяю запрос и избавляюсь от $ numberLong:

db.getCollection('my-collection').find({ "$and" : [{ "timestamp" : { "$gte" : 1582707873806 } }, { "timestamp" : { "$lt" : 1582887165858 } }] })

, он работает как чудо.

Может кто-нибудь просветить меня и объяснить, что я делаю неправильно? Как это сделать правильно? Как заставить данные пружины mon go создать правильный запрос?

Нет необходимости говорить, что строка и целые числа работают отлично. Речь идет о ДОЛГО с.

Заранее спасибо за помощь.

1 Ответ

0 голосов
/ 28 февраля 2020

Как я понимаю:

  • from / to являются единственными параметрами в запросе
  • , оба могут иметь значение null

, и при условии, что ваша модель:

public class Regular {
  @Id
  private String id;

  @Field
  private Long timestamp;
}

Тогда возможное решение (ИМХО намного короче):

// exists(true) is a "hack" to return the elements in case both from/to are null
public List<Regular> find(Long from, Long to) {

  var criteria = where("timestamp").exists(true);
  if(from != null) {
    criteria.gte(from);
  }
  if(to != null) {
    criteria.lte(to);
  }

  return mongoTemplate.find(Query.query(criteria), Regular.class);
}

PS. Я проверил это с Spring Boot 2.2.4 и Пн go 3.6 .

PS2. Тем не менее, вы можете обработать случай, когда from / to оба равны null на extra, если условие и затем удалить существующие (true) .

...