2013-06-22 1 views
4

У нас есть прецедент, в котором пользователь может передавать произвольные критерии поиска для коллекции и хочет, чтобы выводился вывод. Использование хранилищ Spring Data, это довольно просто, если мы знаем заранее, какие атрибуты они могут искать по простым простирающийся MongoRepository и объявить:Возможно ли использовать репозиторий SpringData MongoDB для выполнения произвольного запроса с разбиением на страницы?

Page<Thing> findByFooAndBarAndBaz(Type foo, Type bar, Type baz, Pageable page)

Однако, если мы формируем в запросе себя либо с помощью свободный интерфейс или построение строки mongo и обертывание его в классе BasicQuery, я не могу найти способ получить это в экземпляр репозитория. Существует нет:

Page<Thing> findByQuery(Query q, Pageable page)

функциональность, что я был в состоянии видеть.

Я также не вижу, как подключиться к функции запроса MongoTemplate с абстракцией страницы.

Я надеюсь, что мне не нужно качать собственный пейджинг (вычислять параметры пропуска и ограничения, которые, как я полагаю, не сложно) и напрямую обращаться к шаблону, но я думаю, что могу, если это лучший выбор.

ответ

4

Я не думаю, что это можно сделать так, как я надеялся, но я придумал обходной путь. В качестве фона мы поместили все наши методы для доступа к данным в DAO и некоторых делегатов в репозиторий, а некоторые - к шаблону.

  • Написал метод DAO, который принимает нашу произвольную строку фильтра (который у меня есть утилита, которая преобразует его в стандартное Монго JSON синтаксис запроса.
  • Wrap, что в BasicQuery, чтобы получить «countQuery».
  • Используйте эту countQuery, чтобы получить общее количество записей с помощью MongoTemplate#count(Query, Class)
  • Append моих критериев пейджинга, чтобы создать «pageQuery» с помощью Query#with(Pageable)
  • Запускать pageQuery с MongoTemplate#find(Query, Pageable)
  • Получите List<T> результат: Pageable, который использовался для запроса, и count, возвращенный из прогона countQuery, и постройте новый PageImp, чтобы вернуться к вызывающему.

В основном, это (DocDbDomain класс тест домен для тестирования из документа дб материал):

Query countQuery = new BasicQuery(toMongoQueryString(filterString)); 
    Query pageQuery = countQuery.with(pageRequest); 
    long total = template.count(countQuery, DocDbDomain.class); 

    List<DocDbDomain> content = template.find(pageQuery, DocDbDomain.class); 

    return new PageImpl<DocDbDomain>(content, pageRequest, total); 
+0

Похоже, что это единственный вариант для достижения этой цели. Через 3 года появилась какая-либо другая альтернатива? –

2

Вы можете использовать @Query аннотацию выполнить произвольный запрос через репозиторий метода:

interface PersonRepository extends Repository<Person, Long> { 

    @Query("{ 'firstname' : ?0 }") 
    Page<Person> findByCustomQuery(String firstname, Pageable pageable); 
} 

Вообще говоря, @Query может содержать любой запрос JSON, который вы можете выполнить через оболочку, но с типом синтаксиса ?0 для замены paramete r. Дополнительную информацию об основном механизме можно найти в файле reference documentation.

+1

привет. Это единственный вариант? Потому что он не подходит для реальных случаев. Например, у меня есть подробный поисковый запрос с большим количеством полей, но эти поля могут возникать или не возникать в запросе. Поэтому писать их в '@ Query' не вариант. Mongodb не принимает нулевые критерии более одного раза, а также дает значение null для запроса изменений полей запроса. – barbakini

0

Если вы не можете выразить свой запрос в пределах @Query -Интеграция, вы можете использовать Spring Repository PageableExecutionUtils для своих пользовательских запросов.

Например, как это:

@Override 
public Page<XXX> findSophisticatedXXX(/* params, ... */ @NotNull Pageable pageable) { 

    Query query = query(
      where("...") 
      // ... sophisticated query ... 
    ).with(pageable); 

    List<XXX> list = mongoOperations.find(query, XXX.class); 
    return PageableExecutionUtils.getPage(list, pageable, 
      () -> mongoOperations.count(query, XXX.class)); 
} 

Как и в оригинальной Spring Data Repository, то PageableExecutionUtils будет делать отделенный count запрос и завернуть его в красивый Page для вас.

Here вы можете видеть, что весна делает то же самое.