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.