Skip to content

Commit 1d77025

Browse files
committed
Add support for string ids
1 parent 4571398 commit 1d77025

File tree

3 files changed

+52
-24
lines changed

3 files changed

+52
-24
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ const server = new ApolloServer({
135135

136136
### Caching
137137

138-
To enable shared application-level caching, you do everything from the above section, and you add the `ttl` option to `findOneById()`:
138+
To enable shared application-level caching, you do everything from the above section, and you add the `ttl` (in seconds) option to `findOneById()`:
139139

140140
```js
141141
const MINUTE = 60
@@ -222,6 +222,8 @@ const server = new ApolloServer({
222222

223223
## API
224224

225+
The type of the `id` argument must match the type used in the database. We currently support ObjectId and string types.
226+
225227
### findOneById
226228

227229
`this.findOneById(id, { ttl })`

src/__tests__/cache.test.js

+38-22
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,21 @@ import { EJSON } from 'bson'
55

66
import { createCachingMethods, idToString } from '../cache'
77

8+
const hexId = 'aaaa0000bbbb0000cccc0000'
9+
810
const docs = {
9-
id1: {
10-
_id: 'aaaa0000bbbb0000cccc0000'
11+
one: {
12+
_id: ObjectId(hexId)
1113
},
12-
id2: {
14+
two: {
1315
_id: ObjectId()
1416
}
1517
}
1618

19+
const stringDoc = {
20+
_id: 's2QBCnv6fXv5YbjAP'
21+
}
22+
1723
const collectionName = 'test'
1824
const cacheKey = id => `mongo-${collectionName}-${idToString(id)}`
1925

@@ -32,12 +38,16 @@ describe('createCachingMethods', () => {
3238
() =>
3339
resolve(
3440
ids.map(id => {
35-
if (id.equals(new ObjectId(docs.id1._id))) {
36-
return docs.id1
41+
if (id === stringDoc._id) {
42+
return stringDoc
43+
}
44+
45+
if (id.equals(docs.one._id)) {
46+
return docs.one
3747
}
3848

39-
if (id.equals(docs.id2._id)) {
40-
return docs.id2
49+
if (id.equals(docs.two._id)) {
50+
return docs.two
4151
}
4252
})
4353
),
@@ -59,16 +69,22 @@ describe('createCachingMethods', () => {
5969
})
6070

6171
it('finds one', async () => {
62-
const doc = await api.findOneById(docs.id1._id)
63-
expect(doc).toBe(docs.id1)
72+
const doc = await api.findOneById(docs.one._id)
73+
expect(doc).toBe(docs.one)
74+
expect(collection.find.mock.calls.length).toBe(1)
75+
})
76+
77+
it('finds one with string id', async () => {
78+
const doc = await api.findOneById(stringDoc._id)
79+
expect(doc).toBe(stringDoc)
6480
expect(collection.find.mock.calls.length).toBe(1)
6581
})
6682

6783
it('finds two with batching', async () => {
68-
const foundDocs = await api.findManyByIds([docs.id1._id, docs.id2._id])
84+
const foundDocs = await api.findManyByIds([docs.one._id, docs.two._id])
6985

70-
expect(foundDocs[0]).toBe(docs.id1)
71-
expect(foundDocs[1]).toBe(docs.id2)
86+
expect(foundDocs[0]).toBe(docs.one)
87+
expect(foundDocs[1]).toBe(docs.two)
7288

7389
expect(collection.find.mock.calls.length).toBe(1)
7490
})
@@ -82,31 +98,31 @@ describe('createCachingMethods', () => {
8298
// })
8399

84100
it(`doesn't cache without ttl`, async () => {
85-
await api.findOneById(docs.id1._id)
101+
await api.findOneById(docs.one._id)
86102

87-
const value = await cache.get(cacheKey(docs.id1._id))
103+
const value = await cache.get(cacheKey(docs.one._id))
88104
expect(value).toBeUndefined()
89105
})
90106

91107
it(`caches`, async () => {
92-
await api.findOneById(docs.id1._id, { ttl: 1 })
93-
const value = await cache.get(cacheKey(docs.id1._id))
94-
expect(value).toEqual(EJSON.stringify(docs.id1))
108+
await api.findOneById(docs.one._id, { ttl: 1 })
109+
const value = await cache.get(cacheKey(docs.one._id))
110+
expect(value).toEqual(EJSON.stringify(docs.one))
95111

96-
await api.findOneById(docs.id1._id)
112+
await api.findOneById(docs.one._id)
97113
expect(collection.find.mock.calls.length).toBe(1)
98114
})
99115

100116
it(`caches with ttl`, async () => {
101-
await api.findOneById(docs.id1._id, { ttl: 1 })
117+
await api.findOneById(docs.one._id, { ttl: 1 })
102118
await wait(1001)
103119

104-
const value = await cache.get(cacheKey(docs.id1._id))
120+
const value = await cache.get(cacheKey(docs.one._id))
105121
expect(value).toBeUndefined()
106122
})
107123

108124
it(`deletes from cache`, async () => {
109-
for (const doc of [docs.id1, docs.id2]) {
125+
for (const doc of [docs.one, docs.two, stringDoc]) {
110126
await api.findOneById(doc._id, { ttl: 1 })
111127

112128
const valueBefore = await cache.get(cacheKey(doc._id))
@@ -120,7 +136,7 @@ describe('createCachingMethods', () => {
120136
})
121137

122138
it('deletes from DataLoader cache', async () => {
123-
for (const id of [docs.id1._id, docs.id2._id]) {
139+
for (const id of [docs.one._id, docs.two._id, stringDoc._id]) {
124140
await api.findOneById(id)
125141
expect(collection.find).toHaveBeenCalled()
126142
collection.find.mockClear()

src/cache.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,17 @@ import { EJSON } from 'bson'
55
import { getCollection } from './helpers'
66

77
export const idToString = id => (id instanceof ObjectId ? id.toHexString() : id)
8-
const stringToId = str => str instanceof ObjectId ? str : new ObjectId(str)
8+
const stringToId = str => {
9+
if (str instanceof ObjectId) {
10+
return str
11+
}
12+
13+
if (ObjectId.isValid(str)) {
14+
return new ObjectId(str)
15+
}
16+
17+
return str
18+
}
919

1020
// https://github.com/graphql/dataloader#batch-function
1121
const orderDocs = ids => docs => {

0 commit comments

Comments
 (0)