Skip to content

Commit a35bba8

Browse files
committed
Fix findByFields for nested fields
1 parent b589d16 commit a35bba8

File tree

4 files changed

+67
-8
lines changed

4 files changed

+67
-8
lines changed

src/__tests__/cache.test.js

+17-2
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,22 @@ import {
1313
import { log } from '../helpers'
1414

1515
const hexId = '5cf82e14a220a607eb64a7d4'
16+
const objectID = ObjectId(hexId)
1617

1718
const docs = {
1819
one: {
19-
_id: ObjectId(hexId),
20+
_id: objectID,
2021
foo: 'bar',
2122
tags: ['foo', 'bar']
2223
},
2324
two: {
2425
_id: ObjectId(),
2526
foo: 'bar'
27+
},
28+
three: {
29+
nested: {
30+
_id: objectID
31+
}
2632
}
2733
}
2834

@@ -150,14 +156,23 @@ describe('createCachingMethods', () => {
150156
})
151157

152158
it('finds by ObjectID field', async () => {
153-
const foundDocs = await api.findByFields({ _id: ObjectId(hexId) })
159+
const foundDocs = await api.findByFields({ _id: objectID })
154160

155161
expect(foundDocs[0]).toBe(docs.one)
156162
expect(foundDocs.length).toBe(1)
157163

158164
expect(collection.find.mock.calls.length).toBe(1)
159165
})
160166

167+
// it('finds by nested ObjectID field', async () => {
168+
// const foundDocs = await api.findByFields({ 'nested._id': objectID })
169+
170+
// expect(foundDocs[0]).toBe(docs.three)
171+
// expect(foundDocs.length).toBe(1)
172+
173+
// expect(collection.find.mock.calls.length).toBe(1)
174+
// })
175+
161176
it('finds by array field', async () => {
162177
const foundDocs = await api.findByFields({ tags: 'bar' })
163178

src/__tests__/datasource.test.js

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { MongoClient } from 'mongodb'
1+
import { MongoClient, ObjectId } from 'mongodb'
22
import mongoose, { Schema, model } from 'mongoose'
33

44
import { MongoDataSource } from '../datasource'
@@ -25,7 +25,7 @@ describe('MongoDataSource', () => {
2525
})
2626
})
2727

28-
const URL = 'mongodb://localhost:27017/test'
28+
const URL = 'mongodb://localhost:27017/test-apollo-datasource'
2929
const connectArgs = [
3030
URL,
3131
{
@@ -41,10 +41,14 @@ const connect = async () => {
4141
return client.db()
4242
}
4343

44+
const hexId = '5cf82e14a220a607eb64a7d4'
45+
const objectID = ObjectId(hexId)
46+
4447
describe('Mongoose', () => {
4548
let UserModel
4649
let userCollection
4750
let alice
51+
let nestedBob
4852

4953
beforeAll(async () => {
5054
const userSchema = new Schema({ name: 'string' })
@@ -57,6 +61,12 @@ describe('Mongoose', () => {
5761
{ name: 'Alice' },
5862
{ upsert: true, new: true }
5963
)
64+
65+
nestedBob = await userCollection.findOneAndReplace(
66+
{ name: 'Bob' },
67+
{ name: 'Bob', nested: [{ _id: objectID }] },
68+
{ new: true, upsert: true }
69+
)
6070
})
6171

6272
test('isCollectionOrModel', () => {
@@ -103,8 +113,20 @@ describe('Mongoose', () => {
103113
test('Data Source with Collection', async () => {
104114
const users = new Users(userCollection)
105115
users.initialize()
116+
106117
const user = await users.findOneById(alice._id)
118+
107119
expect(user.name).toBe('Alice')
108120
expect(user.id).toBeUndefined()
109121
})
122+
123+
test('nested findByFields', async () => {
124+
const users = new Users(userCollection)
125+
users.initialize()
126+
127+
const [user] = await users.findByFields({ 'nested._id': objectID })
128+
129+
expect(user).toBeDefined()
130+
expect(user.name).toBe('Bob')
131+
})
110132
})

src/cache.js

+25-3
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,31 @@ export function prepFields(fields) {
4444
return { loaderKey: EJSON.stringify(cleanedFields), cleanedFields }
4545
}
4646

47+
// getNestedValue({ nested: { foo: 'bar' } }, 'nested.foo')
48+
// => 'bar'
49+
function getNestedValue(object, string) {
50+
string = string.replace(/\[(\w+)\]/g, '.$1') // convert indexes to properties
51+
string = string.replace(/^\./, '') // strip a leading dot
52+
var a = string.split('.')
53+
for (var i = 0, n = a.length; i < n; ++i) {
54+
var k = a[i]
55+
if (k in object) {
56+
object = object[k]
57+
} else {
58+
return
59+
}
60+
}
61+
return object
62+
}
63+
4764
// https://github.com/graphql/dataloader#batch-function
4865
// "The Array of values must be the same length as the Array of keys."
4966
// "Each index in the Array of values must correspond to the same index in the Array of keys."
50-
const orderDocs = fieldsArray => docs =>
67+
const orderDocs = (fieldsArray, docs) =>
5168
fieldsArray.map(fields =>
5269
docs.filter(doc => {
5370
for (let fieldName of Object.keys(fields)) {
54-
const fieldValue = fields[fieldName]
71+
const fieldValue = getNestedValue(fields, fieldName)
5572

5673
if (typeof fieldValue === 'undefined') continue
5774

@@ -107,21 +124,26 @@ export const createCachingMethods = ({ collection, model, cache }) => {
107124
if (existingFieldsFilter) return filterArray
108125
return [...filterArray, filter]
109126
}, [])
127+
log('filterArray: ', filterArray)
110128

111129
const filter =
112130
filterArray.length === 1
113131
? filterArray[0]
114132
: {
115133
$or: filterArray
116134
}
135+
log('filter: ', filter)
117136

118137
const findPromise = model
119138
? model.find(filter).exec()
120139
: collection.find(filter).toArray()
121140

122141
const results = await findPromise
123-
const orderedDocs = orderDocs(fieldsArray)(results)
142+
log('results: ', results)
143+
144+
const orderedDocs = orderDocs(fieldsArray, results)
124145
log('orderedDocs: ', orderedDocs)
146+
125147
return orderedDocs
126148
})
127149

src/helpers.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ export const isCollectionOrModel = x =>
1515

1616
export const getCollection = x => (isModel(x) ? x.collection : x)
1717

18-
const DEBUG = false
18+
const DEBUG = true
1919

2020
export const log = (...args) => DEBUG && console.log(...args)

0 commit comments

Comments
 (0)