AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 77590134
Accepted
Lance
Lance
Asked: 2023-12-02 19:20:12 +0800 CST2023-12-02 19:20:12 +0800 CST 2023-12-02 19:20:12 +0800 CST

Exemplo de uma consulta GraphQL em que existem vários tipos de filtro diferentes em um único tipo de registro, dependendo de onde ele está localizado na árvore de consulta?

  • 772

Estou pedindo ajuda ao ChatGPT para aprofundar as possibilidades de consulta do GraphQL, enquanto estou brincando em criar uma variante JSON do GraphQL para fins de aprendizagem. Uma coisa que me deixa perplexo há algum tempo é como você pode oferecer suporte a argumentos/parâmetros de entrada de consulta em um nó, mas não em outro do mesmo tipo de nó.

Construindo aquele longo tópico do ChatGPT (que você não precisa ler para esta postagem), digamos que você tenha um tipo de sistema como este:

const resolvers = {
  Query: {
    author: (parent, args) => {
      // Implement logic to fetch an author by ID
    },
    post: (parent, args) => {
      // Implement logic to fetch a post by ID
    },
  },
  Author: {
    posts: (author) => {
      // Implement logic to fetch all posts by this author
    },
  },
  Post: {
    comments: (post) => {
      // Implement logic to fetch all comments for this post
    },
  },
  Comment: {
    author: (comment) => {
      // Implement logic to fetch the author of this comment
    },
  },
};

Estou tentando imaginar uma imagem onde você tenha algo como esta consulta:

query {
  author(id: "1") {
    id
    name
    posts(limit: 10) {
      id
      title
      content
      comments(limit: 10) {
        id
        text
        author {
          id
          name
          posts(createdAtGt: someDate) {
            id
            title
            content
          }
        }
      }
    }
  }
}

Ou algo ainda mais complexo.

Basicamente, vemos aqui que existe Query.authore também Comment.author, então a primeira parte da pergunta é: por que você precisa do Comment.authorescopo, por que não apenas usar o Query.authorescopo? Não é como se estivéssemos criando um Author.posts.comments()escopo; em vez disso, temos um Post.commentsresolvedor de nível superior.

Mas e se tivéssemos uma situação em que (e ainda não consigo encontrar um exemplo simples e claro) você quisesse filtrar de uma maneira as postagens de author.posts, mas de uma maneira completamente diferente comment.author.posts, _e não quisesse permitir a filtragem de postagens em um contexto para serem usadas na consulta GraphQL no outro contexto na árvore de consulta...

Você já se deparou com essa situação?

Basicamente, estou me perguntando por que você escolheria uma direção em vez de outra:

  1. Permitir que apenas 1 tipo de filtragem funcione em todos os nós/registros de um tipo específico.
  2. Ou 2, especifique uma funcionalidade exclusiva de entrada/filtragem em nível por ramificação, de modo que um tipo de registro possa ter 10 mecanismos de filtragem diferentes com base em sua localização na árvore de consulta.

Se (2) acontecer em aplicativos de produção mais complexos, parece que você teria que reimplementar muita lógica básica em vários pontos diferentes nos resolvedores e, em seguida, personalizar onde for necessário. Basicamente me perguntando por que você não criaria um resolvedor mais parecido com este (lembrando que estou pensando em uma alternativa JSON ao GraphQL para fins de aprendizado):

{
  author: {
    resolve(parent, args) {
      // Find author by id
    },
    children: {
      posts: {
        resolve(parent) {
          // find posts by author id, and allow `limit` on the posts query, only here.
        },
        children: {
          comments: {
            resolve(parent) {
              // find comments by post id
            },
            children: {
              author: {
                resolve(parent) {
                  // find author by comment author id
                },
                children: {
                  posts: {
                    resolve(parent) {
                      // find posts by author id, but only allow searching for greater than certain date.
                    }
                  }
                }
              }
            }
          }
        }
      },
      comments: {
        resolve(parent) {
          // now find comments by author id
        },
        children: {
          author: {
            resolve(parent) {
              // maybe here we have different logic and only return authors with a first name starting with "A".
            },
            children: {
              posts: {
                resolve(parent) {
                  // and another variant here too... it can go on more and more custom cases.
                }
              }
            }
          }
        }
      }
    }
  }
}

Algo assim ocorre no mundo do GraphQL? Em caso afirmativo, qual é um exemplo semicomplexo para demonstrar? Se não, por que não?

graphql
  • 1 1 respostas
  • 27 Views

1 respostas

  • Voted
  1. Best Answer
    Michel Floyd
    2023-12-03T02:33:05+08:002023-12-03T02:33:05+08:00

    Sua pergunta:

    query {
      author(id: "1") {
        id
        name
        posts(limit: 10) {
          id
          title
          content
          comments(limit: 10) {
            id
            text
            author {
              id
              name
              posts(createdAtGt: someDate) {
                id
                title
                content
              }
            }
          }
        }
      }
    }
    

    É perfeitamente razoável no GraphQL.

    1. A seleção de authorby idseria controlada no resolvedor da authorconsulta.

    Eu recomendo nomear suas consultas com algo diferente de nomes de campos apenas para reduzir a ambiguidade

    1. O posts resolvedor de campo para o Authortipo precisa então examinar o argsparâmetro para encontrar o limite 'createdAtGt arguments alongside theparent argument. In the case of the firstposts field, the parent will be theAuthor withid==1 . Later under comments the Author parent for theposts field resolver will be some otherAuthor` que comentou na postagem do autor original.
    2. O commentsresolvedor de campo sob o Posttipo também precisa examinar seu pai e o argsparâmetro para descobrir quais comentários incluir.
    3. O postsresolvedor de campo não precisa se preocupar com a profundidade em que está sendo chamado, o pai e o argssão tudo o que precisa.

    Com isso em mente, estas outras consultas também seriam válidas:

    query {
      author(id: "1") {
        id
        name
        posts(createdAtGt: someDate) {
          id
          title
          content
          comments(limit: 10) {
            id
            text
            author {
              id
              name
              posts(limit: 10) {
                id
                title
                content
              }
            }
          }
        }
      }
    }
    
    query {
      author(id: "1") {
        id
        name
        posts(limit: 10, createdAtGt: someDate) {
          id
          title
          content
          comments(limit: 10) {
            id
            text
            author {
              id
              name
              posts(createdAtGt: someDate, limit: 10) {
                id
                title
                content
              }
            }
          }
        }
      }
    }
    

    Agora, para a próxima parte da pergunta:

    Mas e se tivéssemos uma situação em que (e ainda não consigo encontrar um exemplo simples e claro) você quisesse filtrar de uma forma as postagens de author.posts, mas de uma maneira completamente diferente em comment.author.posts, _e você não Não quero permitir que a filtragem de postagens em um contexto seja usada na consulta GraphQL em outro contexto na árvore de consulta...

    Pode-se anexar quaisquer dados desejados a um objeto ao resolvê-lo. Esses dados extras são transmitidos aos resolvedores filhos, mas eliminados quando a árvore JSON é retornada ao cliente.

    Assim, por exemplo, no commentresolvedor under post when you resolve theautor you could add anisCommentAuthor key to theautor object and then theposts resolver underAuthor` poderia verificar se essa chave está no pai e então resolver de forma diferente.

    Alternativamente, você pode estender o Authortipo para um CommentAuthortipo (com todos os mesmos campos e talvez alguns outros) e então ter um resolvedor completamente diferente para postsunder CommentAuthordo que você faz under Author.

    Cada uma dessas soluções pode parecer desajeitada em alguma dimensão, mas já foi feita antes.

    Há alguma tensão inerente à sua pergunta entre o que um desenvolvedor front-end pode querer da consulta e como o desenvolvedor back-end deseja restringir possíveis resultados. Normalmente, o desenvolvedor back-end deve (opinião) fornecer flexibilidade máxima, ao mesmo tempo em que aplica regras de segurança e fornece alto desempenho. Definitivamente, é difícil para o desenvolvedor back-end prever todas as formas como uma consulta pode aparecer. Fazer com que os resolvedores de campo atuem de maneira diferente dependendo de seus avós e bisavós aumenta a complexidade. Certifique-se de que o benefício vale esse custo.

    • 1

relate perguntas

  • Strapi - Excluir um item do componente repetível aninhado

  • Consulta Knex com .where() retorna nulo no GraphQL

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve