Skip to content

Latest commit

History

History
164 lines (127 loc) 路 7.84 KB

fetching-data.mdx

File metadata and controls

164 lines (127 loc) 路 7.84 KB
title description
Fetching Data
Using RESTDataSource to fetch data from REST APIs

Data sources are classes that Apollo Server can use to encapsulate fetching data from a particular source, such as a database or a REST API. These classes help handle caching, deduplication, and errors while resolving operations.

Your server can use any number of different data sources. You don't have to use data sources to fetch data, but they're strongly recommended.

flowchart LR;
  restAPI(REST API);
  db(Database);
  subgraph ApolloServer;
    restDataSource(RESTDataSource);
    DBDataSource(DBDataSource);
  end
  restDataSource --Fetches data--> restAPI;
  DBDataSource --Fetches data--> db;
  client(ApolloClient);
  client --Sends query--> ApolloServer;
  class restAPI,db secondary;

Open-source implementations

All data source implementations extend the generic DataSource abstract class, which is included in the apollo-datasource package. Subclasses of a DataSource should define whatever logic is required to communicate with a particular store or API.

Apollo and the larger community maintain the following open-source implementations:

Do you maintain a DataSource implementation that isn't listed here? Please submit a PR to be added to the list!

Class Source For Use With
RESTDataSource Apollo REST APIs (see below)
HTTPDataSource Community HTTP/REST APIs (newer community alternative to RESTDataSource)
SQLDataSource Community SQL databases (via Knex.js)
MongoDataSource Community MongoDB
CosmosDataSource Community Azure Cosmos DB
FirestoreDataSource Community Cloud Firestore

If none of these implementations applies to your use case, you can create your own custom DataSource subclass.

Apollo does not provide official support for community-maintained libraries. We cannot guarantee that community-maintained libraries adhere to best practices, or that they will continue to be maintained. -->

Adding data sources to Apollo Server's context

You provide your DataSource subclasses to the context initialization function, like so:

//highlight-start
interface ContextValue {
  dataSources: {
    moviesAPI: MoviesAPI;
    personalizationAPI: PersonalizationAPI;
  };
}
//highlight-end

const server = new ApolloServer<ContextValue>({
  typeDefs,
  resolvers,
});

const { url } = await startStandaloneServer(server, {
  context: async ({ req }) => {
    return {
      //highlight-start
      // We create new instances of our data sources with each request
      dataSources: {
        moviesAPI: new MoviesAPI(),
        personalizationAPI: new PersonalizationAPI(),
      },
      //highlight-end
    };
  },
});

console.log(`馃殌  Server ready at ${url}`);

Apollo Server calls the the context initialization function for every incoming operation. This means:

  • As shown above, with every operation context returns an object containing new instances of your DataSource subclasses (in this case, MoviesAPI and PersonalizationAPI).
  • These subclasses are accessible from the the context value argument that's passed between your server's resolvers.
  • The context function should create a new instance of each data source for each operation. If multiple operations share a single data source instance, you might accidentally combine results from multiple operations.

Your resolvers can now access your data sources from the shared context object and use them to fetch data:

const resolvers = {
  Query: {
    movie: async (_, { id }, { dataSources }) => {
      return dataSources.moviesAPI.getMovie(id);
    },
    mostViewedMovies: async (_, __, { dataSources }) => {
      return dataSources.moviesAPI.getMostViewedMovies();
    },
    favorites: async (_, __, { dataSources }) => {
      return dataSources.personalizationAPI.getFavorites();
    },
  },
};

Caching

By default, data source implementations use Apollo Server's in-memory cache to store the results of past fetches.

When you initialize Apollo Server, you can provide its constructor a different cache object that implements the KeyValueCache interface. This enables you to back your cache with shared stores like Memcached or Redis.

const server = new ApolloServer({
  typeDefs,
  resolvers,
  cache: new MyCustomKeyValueCache()
});

Using an external cache backend

When running multiple instances of your server, you should use a shared cache backend. This enables one server instance to use the cached result from another instance.

Apollo Server supports using Memcached, Redis, or other cache backends via the keyv package. For examples, see Configuring external caching.

You can also choose to implement your own cache backend. For more information, see Implementing your own cache backend.