Есть ли альтернатива spring для graphql для netflix @DGSDataloader и DGSData

Попытка перенести проект Netflix DGS GraphQL и Neo4J, чтобы вместо этого использовать Spring для GraphQL и Neo4J. Наткнулся на блокпост, когда хотел избежать проблемы N+1.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Да, есть альтернатива, позволяющая избежать проблемы N+1 в Spring для GraphQL. Это аннотация @BatchMapping:

Предположим, у вас есть следующая схема:

type Query {
    artistas: [Artista]
}

type Artista {
    id: ID
    apellido: String
    estilo: String
    obras:[Obra]
}

type Obra{
    artistaId: ID
    titulo: String
    imagen: String
}

И следующий @QueryMapping:

@QueryMapping
Flux<Artista> artistas(){
    return Flux.fromIterable(allArtistas);
}

Наш DTO Artista содержит список Obra, который нам иногда может понадобиться, поэтому это может вызвать у нас проблему N + 1:

record Artista (Long id, String apellido, String estilo, List<Obra> obras){}
record Obra (Long artistaId, String titulo, String imagen){}

Поэтому, если вы добавите дополнительный метод сопоставления, аннотированный с помощью @BatchMapping, вы скажете механизму GraphQL извлекать эти данные, используя DataLoader под капотом, и держать их под рукой, например, для каждого кругового обхода БД.

@BatchMapping(typeName = "Artista")
Mono<Map<Artista, List<Obra>>> obras(List<Artista> artistas){
    var artistasIds = artistas.stream()
                .map(Artista::id)
                .toList();

    var todasLasObras = obtenerObras(artistasIds);

    return todasLasObras.collectList()
            .map(obras -> {
                Map<Long, List<Obra>> obrasDeCadaArtistaId = obras.stream()
                        .collect(Collectors.groupingBy(Obra::artistaId));

                return artistas.stream()
                        .collect(Collectors.toMap(
                                unArtista -> unArtista, //K, el Artista
                                unArtista -> obrasDeCadaArtistaId.get(Long.parseLong(unArtista.id().toString())))); //V, la lista de obras
            });
}
private Flux<Obra> obtenerObras(List<Long> artistasIds) {
// ...your service-specific way of getting all the Obras from each artistaId...
}

Если вы разбросаете несколько журналов здесь и там, вы можете проверить, что они получают Obras только один раз.

Надеюсь, это поможет!

Другие вопросы по теме