How can resolvers in GraphQL optimize data fetching based on necessity?

I am working with two unique GraphQL types:

type Author {
  id: String!
  name: String!
}

type Book {
  id: String!
  author: Author!
  name: String!
}

Within my database structure, there exists a foreign key inside the books table:

table authors (pseudo code)

`id` INTEGER UNSIGNED
`name` STRING

table books (pseudo code)

`id` INTEGER UNSIGNED
`author_id` INTEGER UNSIGNED REFERENCE `authors.id`
`name` STRING

When resolving a GraphQL query like the following:

query allTheBooks {
  id
  name
  author {
    id
  }
}

I want to avoid executing an additional SQL query beyond the one retrieving the list of books, as the necessary data is already present in the books.author_id field.

To achieve this optimization, I replaced the existing JavaScript code:

Book: {
  async author(book, args, context, info) {
    // this code trigger a database SELECT query that fetch all the fields of the author row associated with the book
    return book.author().get();
  }
}

with:

Book: {
  async author(book, args, context, info) {
    return {
      id: book.author_id,
    }
  }
}

This solution proved to be effective, resulting in only one SQL query being executed where previously there were multiple queries.

However, I am seeking a way to retrieve the other fields without issuing individual queries per field.

I theorize that it may be achievable by returning a single promise for all fields, which would then resolve with the complete contents of the author row. Yet, I am curious if there exists a more streamlined approach...

I appreciate your insights on this matter!

Answer №1

Currently, I have found a somewhat efficient method to accomplish this:

Book: {
  async author(book, args, context, info) {
    let authorPromise = null;

    async function getAuthor() {
      if (authorPromise === null) {
        authorPromise = book.author().get();
      }

      return authorPromise;
    }

    return new Proxy({}, {
      async get({}, name) {
        if (name === "id") {
          return book.author_id;
        }

        if (name in authorFields) {
          const author = await getFile();
          return author[name];
        }
      },
    });
  }
}

This approach allows me to minimize the number of queries per row, though it does raise questions about table joins which I will address in a separate post here :-)

Answer №2

No need to execute individual queries one by one. You have the option to batch multiple queries into a single request. Explore https://github.com/facebook/dataloader for more information.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the purpose of including a function in an AngularJS dependency array?

When it comes to injecting dependencies, the process involves the following steps: inject(["$scope", "$compile", function ($scope, $compile) { ... }]); The syntax used here may seem strange. Placing the function inside the array might appear counter-in ...

Elements that are added dynamically do not contain any space between each other

I have a markup template that looks like this. <template id="unsequenced-template"> <button type="button" class="btn btn-primary railcar"></button> </template> Then, I use the following JavaScript ...

I am interested in developing a JavaScript program that can calculate multiples of 0.10

I am looking to let users input values that are multiples of 0.10, such as - 0.10, 0.20, 0.30....1.00, 1.10, 1.20...1.90, and so on. When a user enters a value in the text box, I have been checking the following validation: amount % 0.10 == 0 Is this a ...

Tips for dynamically assigning values to scope variables in AngularJS

My ng-model looks like this: <tr ng-repeat="user in users"> <input type="text" ng-model="code[user.id]"/> When I set $scope.code = {0: 'value'};, it works fine. However, if I try to pass a dynamic value like: var index = 0; $scope ...

"Discover the method for tallying the quantity of radio buttons based on their names within AngularJS

Can anyone guide me on how to determine the number of radio buttons by name in AngularJS using a directive? <label ng-repeat="elements in [1,2,3,4,5,6,7]"> <input type="radio" name="phone" ng-model="phone" value="example"> </label& ...

Click the button to add a component

I am developing a front-end application using TypeScript and React. Within one of my components, Component A, there is a textbox along with other HTML elements. I want to dynamically add instances of Component A every time a button is clicked. Additionally ...

Defining the range of an array of numbers in TypeScript: A complete guide

When working with Next.js, I created a function component where I utilized the useState hook to declare a variable for storing an array of digits. Here is an example: const [digits, setDigits] = useState<number[]>(); I desire to define the range of ...

Update class name in React component based on state change

My current setup involves the setting of active and class flags as shown below: constructor(props) { super(props); this.state = {'active': false, 'class': 'album'}; } handleClick(id) { if(this.state.active){ this.s ...

Video streaming platform without the need for javascript and plugins

Is it feasible to watch Youtube videos without relying on javascript and plugins, exclusively using HTML5 or a similar alternative? ...

Generate a randomly structured 2D array called "Array" using JavaScript

Can anyone help me with extracting a random array from a 2D named array? I've tried several solutions but none of them seem to work. var sites = []; sites['apple'] = [ 'green' , 'red' , 'blue' ]; sites['o ...

Tips for deleting a specific choice with Angular

Having recently started working with Angular2 / TS / ES6, I am struggling to find a solution to my issue. I have a select element with dynamically rendered options using ngFor from an array. These options are meant for selecting attributes for a product. ...

The EffectComposer in Three.js seems to be malfunctioning when combined with the Bloom

I'm completely stumped trying to troubleshoot the issue with these two mysterious .js files in my project. Despite the lack of documentation, I have implemented the EffectComposer and BloomPass and attempted to call them like this: parameters = { blo ...

Add and remove input fields in real-time while also modifying nested arrays dynamically

Is it possible to dynamically add new input fields to an object within a nested array in React JS when the user clicks on a plus sign? I am looking to dynamically add and remove inputs. I am interested in adding and deleting propositionTimes dynamically u ...

The module 'AppModule' has unexpectedly declared a value of 'Component' that was not anticipated

Recently, I've been working on transitioning my application to the new angular2 webpack rc5 setup. I have successfully generated the app module using ng cli migration. However, I am facing an issue while trying to integrate a component from my own li ...

The edit form components (dropdown and date input) are failing to load properly

I am currently facing a challenge with my project, specifically with the edit form that opens through a modal. This form consists of 8 text fields, 4 dropdowns (2 of which are dynamic dropdowns as discussed in my previous issue), and a single standard date ...

Finding a workaround for the absence of a leftToggle feature in ListItem component of Material-UI

Is there a way to move the toggle element to the other side in Material-UI's listItem without using the leftToggle option? The documentation does not specify a leftToggle attribute, so I am looking for alternative solutions. I would like to align the ...

Creating a seamless and interactive online platform

I am in the process of designing a website that has a sleek and dynamic layout, rather than just a static homepage. Let me explain further: Here is my current setup so you can understand what I am trying to achieve. By dynamic, I mean that when the page ...

Tips for preventing real-time changes to list items using the onchange method

I am facing an issue with a list of items that have an Edit button next to them. When I click the Edit button, a modal pops up displaying the name of the item for editing. However, before clicking the save button, the selected item in the list gets changed ...

Obtaining the width of an object in Three.js using CSSObject3D

In my process, I am dynamically generating HTML Dom Elements from HTML text using a specific function: String.prototype.toDomElement = function () { var wrapper = document.createElement('div'); wrapper.className = "toDomWrapper"; wrapper.i ...

Merging and Reorganizing files using Gulp based on Folder names

In my gulpfile.js, I am attempting to configure a setup that concatenates all .js files located in the src/js folder and names them based on their parent folder. Here is an example of the folder structure: project | +-assets | | | +-app.min.js | | | +-ve ...