Zastanawiam się czy da się jakoś połączyć projekcje MongoDB z data class
Kotlina, któego pola są non-nullable.
Przykład - mam API GraphQLowe, z taką schemą
type Query {
books: [Book]
}
type Book {
id: ID!
title: String!
author: String!
pagesCount: Int!
}
No i mój kod sprowadza się do czegoś takiego
@Document(collection = "book")
data class Book(@Id val id: String? = null,
val title: String,
val author: String,
val pagesCount: Int)
@Repository
class BookRepository(private val mongoTemplate: MongoTemplate) {
fun findAll(): List<Book> = mongoTemplate.findAll(Book::class.java)
}
@Component
class BookResolver(private val bookRepository: BookRepository): GraphQLQueryResolver {
fun books() = bookRepository.findAll()
}
I działa, mogę skonstruować query GraphQL tak by wyciągnąć np. tylko title
i pagesCount
i klient korzystający z API dostanie tylko te dwa pola. Po stronie bazy danych, jednak nadal wyciągać będę cały obiekt Book
, również pola które mnie nie interesują, które potencjalnie mogą być jakimiś dużymi obiektami.
Alternatywa to zrobienie czegoś takiego
@Document(collection = "book")
data class BookProjection(val title: String, val pagesCount: Int)
Jednak oznacza to, że potrzebowałbym takie projekcje dla każdej możliwej kombinacji pól w Book
.
No ale mongoTemplate
udostępnia opcje, by wskazać które pola chcę wyciągnąć, mógłym więc wymagane parametry przechwycić z query GraphQL i uzyć tutaj.
fun findBooksProjection(): List<Book> {
val query = Query()
query.fields().include("title", "pagesCount")
return mongoTemplate.find(query, Book::class.java)
}
Tyle, że to oczywiście nie zadziała, bo mój data class
ma wszystkie pola non-nullable
Failed to instantiate com.example.demo.Book using constructor fun <init>(kotlin.String?, kotlin.String, kotlin.String, kotlin.Int):
No więc pytanie, czy jest na to jakiś sposób inny niż oznaczenie wszytkich pól w takim dokumencie jako nullable? Teoretycznie mógłbym system podzielić wg. CQRS i w przypadku query wyciągać coś w rodzaju wspomnianego BookProjection
, jednak ze wszystkimi polami nullable, wtedy nie ma już tyle logiki i potencjalnych nulli obsługi co w przypadku command, gdzie nadal mógłym działać na pierwotnej encji. Chciałbym się jednak upewnić czy nie ma innej drogi, może Kotlin zaskoczy mnie czymś jeszcze.