Нарезанные проекции с помощью Spring Data MongoDB ReactiveMongoRepository? - PullRequest
0 голосов
/ 04 июня 2018

У меня есть коллекция с именем myCollection, которая содержит документы в следующем формате:

{
    "_id" : "1",
    "myArray" : [ { x: 1, y: "a" }, { x: 2, y: "b" }, { x: 3, y: "c" }, { x: 4, y: "d" }, { x: 5, y: "e" }]
}

Что я хотел бы сделать, это создать запрос, который возвращает слайс из некоторых элементов в myArray как проекция.

Т.е. скажем, что мой документ определен так:

@Document(collection = "myCollection")
data class MyDocument(@Id val myId : String, val myArray : List<MyItem>)

, где MyItem определено так:

data class MyItem(val x: Int, val y: String)

Теперь я хочу создать функцию, которая возвращает список MyItem с заданным смещением и количеством элементов (или «страницей») для MyDocument с определенным идентификатором.

Вот что я пробовал (используя проекции ):

data class MyArrayProjection(val myArray: List<MyItem>)

interface MyRepository : ReactiveMongoRepository<MyDocument, String> {             
    fun findByMyId(myId: String, pageable: Pageable): Flux<MyArrayProjection>
}

То, что я хотел бы увидеть при вызове этой функции, например,

myRepository.findByMyId("1", PageRequest.of(1, 2))

, эточто он возвращает Flux, содержащий MyItem(x=3, y="c") и MyItem(x=4, y="d"), но вместо этого он пустой.

Сгенерированный запрос MongoDB выглядит следующим образом:

{
    "find" : "myCollection",
    "filter" : {
        "_id" : "1"
    },
    "projection" : {
        "myArray" : 1
    },
    "skip" : 2,
    "limit" : 2,
    "batchSize" : 256
}

Что я подозреваю, происходит то, чтоэкземпляр Pageable работает с агрегатом (MyDocument), а не "внутри" поля myArray, поэтому я подозреваю, что хочу сомкак вместо этого использовать оператор $ slice .

Как этого добиться?Если он не будет работать с использованием ReactiveMongoRepository , тогда я в порядке с использованием ReactiveMongoOperations .

1 Ответ

0 голосов
/ 05 июня 2018

Мне удалось решить эту проблему, изменив:

interface MyRepository : ReactiveMongoRepository<MyDocument, String> {             
    fun findByMyId(myId: String, pageable: Pageable): Flux<MyArrayProjection>
}

на:

interface MyRepository : ReactiveMongoRepository<MyDocument, String> {             
    @Query(value = "{ '_id' : ?0 }", fields = "{ 'myArray': { '\$slice': ?1 } }")
    fun findByMyId(myId: String, slice: Array<Int>): Flux<MyArrayProjection>
}

и затем вызвав его с помощью:

myRepository.findByMyId("1", arrayOf(1, 2))
...