Paging Flow Solution JavaScript Code

Viewing Data via GraphQL

Paging Flow Solution JavaScript Code

🙋 Need help? Ask an expert now!

JS Code Implementing Smart Paging

Folder src/paging-processor contains the set of functions that map the paging parameters we've seen in node_modules/graphql-relay/lib/connection/connection.js to a generic function launcher that executes individual MongoDB queries written to extract specific datasets.

MongoDB Query Launcher

src/paging-processor/find-with-paging.js is the component where the database query function gets called:

    return await execDetails.queryFunction(
      args.filterValues,
      aggregateArray,
      viewerLocale,
      execDetails.fetchParameters
    );

Function execDetails.queryFunction is called with the arguments listed. execDetails is an object that we define in the GraphQL paging query schema resolver function. E.g., the listUsers resolver in src/relay-resolvers/user-resolver.js:

const businessKey = '_id';
const fetchParameters = {};

const execDetails = {
    queryFunction: fetchUserList,
    businessKey: businessKey,
    fetchParameters: fetchParameters
  };

business key points to a field in the underlying MongoDB document that is used to uniquely identify the database record linked to the cursor. The value of that field is loaded into the cursor - we saw that in the previous lesson. In the context of the lisUsers query, the business key is the _id field of the User Collection. An _id would be used as the business key often, but not necessarily always - there maybe other fields in the MongoDB schema that are unique relatively to what the query returns, especially if the return dataset doesn't directly correspond to a MongoDB Document. Remember, we added _id to some embedded MongoDB fields as well - ensuring that we have unique identifiers at all levels that may be used as datasets. Back to what we discussed in the previous lesson - a generic GraphQL-MongoDB solution can surely be built over a database schema structure fitting exactly each GraphQL query, but it would impose severe limitations on the database design. Pretty much, the MongoDB schema would need to be very dry and resemble a Graph database. We don't learn about Graph databases in this course. Relational and NoSQL cover enough application use case ground for a backend developer.

Back to the arguments, queryFunction is what runs the MongoDB query. Here, it is fetchUserList imported in this line:

import { fetchUserList } from '../db-handlers/user/user-list-fetch';

The fetchParameters argument contains the filtering info to be passed to the database query. Generally, it is assembled in the query resolver from the GraphQL query arguments. As in this query we list all users, no filtering applies.

Back to the execDetails.queryFunction call, we also pass:

  • args.filterValues directly from the query. This argument is included mostly for system-to-system type of interfaces; it is not a good practice opening direct query access to users, so this parameter is ignored in most DB query builders in the demo project
  • aggregateArray - the evaluated combination of sort and limit per the GraphQL query, as well as skip based on the paging logic

Utility Methods

src/paging-processor/aggregate-array-builder.js and src/paging-processor/connection-from-datasource.js contain utility methods executing the logic that assigns the aggregateArray parameter values and carries out the cursor-related work. Most of the code is written in a traditional if-then-else format that is easy to understand and follow through. There is nothing special in there, just working through the steps we detailed in the previous lesson.

That concludes the smart paging solution overview. Now as you see it action in the GrapiQL results and console logging, you know exactly what it does, how and why.


Next, will look at the GraphQL Input Type schemas defined in src/relay-queries/input-types-get-query.js. Those are used to manage common query input structures on the client side and their mapping into what the server receives

Edit Me on GitHub!