Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

234
Visualizações
Construct MongoDB query from GraphQL request

Let's say we query the server with this request, we only want to get the following user's Email, My current implementation requests the whole User object from the MongoDB, which I can imagine is extremely inefficient.

GQL
{
  user(id:"34567345637456") {
    email
  }
}

How would you go about creating a MongoDB filter that would only return those Specified Fields? E.g,

JS object
{
   "email": 1
}

My current server is running Node.js, Fastify and Mercurius

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

which I can imagine is extremely inefficient.

Doing this task is an advanced feature with many pitfalls. I would suggest starting building a simple extraction that read all the fields. This solution works and does not return any additional field to the client.

The pitfalls are:

  • nested queries
  • complex object composition
  • aliasing
  • multiple queries into one request

Here an example that does what you are looking for. It manages aliasing and multiple queries.

const Fastify = require('fastify')
const mercurius = require('mercurius')

const app = Fastify({ logger: true })

const schema = `
  type Query {
    select: Foo
  }

  type Foo {
    a: String
    b: String
  }
`

const resolvers = {
  Query: {
    select: async (parent, args, context, info) => {
      const currentQueryName = info.path.key

      // search the input query AST node
      const selection = info.operation.selectionSet.selections.find(
        (selection) => {
          return (
            selection.name.value === currentQueryName ||
            selection.alias.value === currentQueryName
          )
        }
      )
      
      // grab the fields requested by the user
      const project = selection.selectionSet.selections.map((selection) => {
        return selection.name.value
      })

      // do the query using the projection
      const result = {}
      project.forEach((fieldName) => {
        result[fieldName] = fieldName
      })

      return result
    },
  },
}

app.register(mercurius, {
  schema,
  resolvers,
  graphiql: true,
})

app.listen(3000)

Call it using:

query {
  one: select {
    a
  }
  two: select {
    a
    aliasMe:b
  }
}

Returns

{
  "data": {
    "one": {
      "a": "a"
    },
    "two": {
      "a": "a",
      "aliasMe": "b"
    }
  }
}
about 4 years ago · Juan Pablo Isaza Relatório

0

Expanding from @Manuel Spigolon original answer, where he stated that one of the pitfalls of his implementation is that it doesn't work on nested queries and 'multiple queries into one request' which this implementation seeks to fix.

function formFilter(context:any) {
    let filter:any = {};

    let getValues = (selection:any, parentObj?:string[]) => {
        //selection = labelSelection(selection);

        selection.map((selection:any) => {
            // Check if the parentObj is defined
            if(parentObj)
                // Merge the two objects
                _.merge(filter, [...parentObj, null].reduceRight((obj, next) => {
                    if(next === null) return ({[selection.name?.value]: 1});
                    return ({[next]: obj});
                }, {}));

            // Check for a nested selection set
            if(selection.selectionSet?.selections !== undefined){
                // If the selection has a selection set, then we need to recurse
                if(!parentObj) getValues(selection.selectionSet?.selections, [selection.name.value]);

                // If the selection is nested
                else getValues(selection.selectionSet?.selections, [...parentObj, selection.name.value]);
            }
        });
    }

    // Start the recursive function
    getValues(context.operation.selectionSet.selections);

    return filter;
}

Input

{
  role(id: "61f1ccc79623d445bd2f677f") {
        name
    users {
      user_name
      _id
      permissions {
        roles
      }
    }
    permissions
  }
}

Output (JSON.stringify)

{
   "role":{
      "name":1,
      "users":{
         "user_name":1,
         "_id":1,
         "permissions":{
            "roles":1
         }
      },
      "permissions":1
   }
}
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda