Socket
Book a DemoInstallSign in
Socket

apollo-datasource-mongo

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

apollo-datasource-mongo

Apollo data source for MongoDB Client and Mongoose

0.1.11
latest
npmnpm
Version published
Weekly downloads
48
45.45%
Maintainers
1
Weekly downloads
 
Created
Source

npm versionBuild Status Coverage Status

Apollo data source for MongoDB

npm i apollo-datasource-mongo

OR

yarn add apollo-datasource-mongo

This package uses DataLoader for batching and per-request memoization caching. It also optionally (if you provide a ttl), does shared application-level caching (using either the default Apollo InMemoryLRUCache or the cache you provide to ApolloServer()**). It does this only for these three methods:

** Tested with Redis only

Contents:

This package works with either one of the following npm packages:

Demo

Usage

Basic

The basic setup is subclassing MongoDataSource, passing your collection to the constructor, and using the API methods:

import { MongoDataSource } from 'apollo-datasource-mongo'

export default Class Users extends MongoDataSource {

  getUser(userId) {
    return this.users.loadOneById(userId)
  }
}

and:

import Users from './data-sources/Users.js'
import { users } from './your-mongo-schema-folder'

const server = new ApolloServer({
  typeDefs,
  resolvers,
  dataSources: () => ({
    db: new Users({ users })
  })
})

The collection is available at this.users (e.g. this.users.update({_id: 'foo, { $set: { name: 'me' }}})). The request's context is available at this.context. For example, if you put the logged-in user's ID on context as context.currentUserId:

class Users extends MongoDataSource {
  ...

  async getPrivateUserData(userId) {
    const isAuthorized = this.context.currentUserId === userId
    if (isAuthorized) {
      const user = await this.users.loadOneById(userId)
      return user && user.privateData
    }
  }
}

If you want to implement an initialize method, it must call the parent method:

class Users extends MongoDataSource {

  initialize(config) {
    super.initialize(config)
    ...
  }
}

For example, you can also enable debugging and whole cache flushing:


class Users extends MongoDataSource {

  initialize(config) {
    super.initialize({
      ...config,
      debug: true,
      allowFlushingCollectionCache: true // to allow flushing collection's cache***
    })
    ...
  }
}

*** By default flushing the collection's cache is not allowed.

Batching

This is the main feature, and is always enabled. Here's a full example:

import { MongoDataSource } from 'apollo-datasource-mongo'
import { users, posts } from './your-mongo-schema-foleder'
class Users extends MongoDataSource {

  getUser(userId) {
    return this.users.loadOneById(userId)
  }
}

class Posts extends MongoDataSource {


  getPosts(postIds) {
    return this.posts.loadManyByIds(postIds)
  }

  getUserPostsByQuery(query) {
    return this.posts.loadManyByQuery(query)
  }
}

const resolvers = {
  Post: {
    author: (post, _, { dataSources: { users } }) => users.getUser(post.authorId)
  },
  User: {
    posts: (user, _, { dataSources: { posts } }) => posts.getPosts(user.postIds),
    lastSevenDaysPosts: (user, _, { dataSources: { posts } }) => posts.getUsersPostsByQuery({
      author: user._id,
      createdAt: { $gt: (new Date()).getDate() - 7 }
    })
  }
}

const server = new ApolloServer({
  typeDefs,
  resolvers,
  dataSources: () => ({
    users: new Users({ users }),
    posts: new Posts({ posts })
  })
})

Caching

To enable shared application-level caching, you do everything from the above section, and you add the ttl option to loadOneById():

const MINUTE = 60

class Users extends MongoDataSource {

  getUser(userId) {
    return this.users.loadOneById(userId, { ttl: MINUTE })
  }

  async updateUserName(userId, newName) {
    await this.users.deleteFromCacheById(userId)
    
    // await this.users.flushCollectionCache() // to flush the whole collection's cache. It needs allowFlushingCollectionCache to be true in the extended config object passed to the initialize method
    // N.B.: Flushing the collection cache works only with Redis. It has no effect otherwise.
    
    return this.users.updateOne({ 
      _id: userId 
    }, {
      $set: { name: newName }
    })
  }
}

const resolvers = {
  Post: {
    author: (post, _, { dataSources: { users }) => db.getUser(post.authorId)
  },
  Mutation: {
    changeName: (_, { userId, newName }, { users, currentUserId }) => 
      currentUserId === userId && users.updateUserName(userId, newName)
  }
}

Here we also call deleteFromCacheById() to remove the user from the cache when the user's data changes. If we're okay with people receiving out-of-date data for the duration of our ttl—in this case, for as long as a minute—then we don't need to bother adding calls to deleteFromCacheById().

API

loadOneById

loadOneById(id, { ttl })

Resolves to the found document. Uses DataLoader to load id. DataLoader uses collection.find({ _id: { $in: ids } }). Optionally caches the document if ttl is set (in whole seconds).

loadManyByIds

loadManyByIds(ids, { ttl })

Calls loadOneById() for each id. Resolves to an array of documents.

loadManyByQuery

loadManyByQuery(query, { ttl })

Resolves to the found documents. Uses DataLoader to load the query. DataLoader uses sift to filter in-memory arrays using MongoDB query objects. Optionally caches the document if ttl is set (in whole seconds).

deleteFromCacheById

deleteFromCacheById(id)

deleteFromCacheById(query)

Deletes a document from the cache.

//

flushCollectionCache

flushCollectionCache()

Deletes all collection's documents from the cache.

//

Forked and extended from

Keywords

apollo

FAQs

Package last updated on 20 Jun 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.