DEV Community

Bipin Shrestha
Bipin Shrestha

Posted on • Originally published at sthabipin.com.np

1 1

Graphql field to select data from the database

The way graphql structures the data fetching architecture is simply awesome. While working with graphql we might have the case where we want to get only certain data from the database. The database has some secret credentials like password, keys, auth ids which we don’t want to disclose even to the API.

So we have to get data from the database dynamically that means select database fields dynamically. For example, if the client selects the only username and email, the graphql API has to fetch only those values from the database.

There are packages that do this for us but we need to avoid installing packages for every bit of the problem. We can do it without any sort of the third packages using the apollo server’s info argument on the resolver.

We are using an apollo server here.
const resolvers = {
  Query: {
    user(parent, args, context, info) {}
}
Enter fullscreen mode Exit fullscreen mode

[info] contains information about the operation's execution state, including the field name, the path to the field from the root, and more. - Apollo server docs

We have the client query:

query userDetail($email: String!) {
  getUser(email: $email){
    username
    email
  }
}
Enter fullscreen mode Exit fullscreen mode

The info arg contains the field name that comes from the client. Now we use it to extract the selection field as:

const fields = info.fieldNodes[0].selectionSet.selections;
const attributes = fields.map(field => field.name.value);

console.log(attributes); // ['username', 'email']
Enter fullscreen mode Exit fullscreen mode

We have both username and email. Now we'll fetch data from the database.

sequelize

const user = await User.findOne({
  where: { email },
  attributes,
});
Enter fullscreen mode Exit fullscreen mode

With mongoose,

const user = await User.findOne({ email }).select(attributes);
Enter fullscreen mode Exit fullscreen mode

We can modify the user further according to our needs and return to the client.

Full code

const resolvers = {
  Query: {
    getUser: async (_, args, __, info) => {
      const { email } = args;

      try {
        const fields = info.fieldNodes[0].selectionSet.selections;
        const attributes = fields.map(field => field.name.value);

        const user = await User.findOne({
          where: { email },
          attributes,
        });

        return user;
      } catch (error) {
        throw error;
      }
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

Final Note

The code above is just for the demo purpose. It might not be the right approach for this kind of simple API but for the more advanced or heavy API, it gives a higher performance as the database selects only given attributes.

Database benchmark also shows selecting only certain fields/attributes increases the query performance because the database only needs to make calculations on given fields.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up