GraphQLGuide / apollo-datasource-mongodb

Apollo data source for MongoDB
MIT License
285 stars 64 forks source link

Proper way to pass ObjectId in findByFields() #65

Closed Daguima-dag closed 3 years ago

Daguima-dag commented 3 years ago

Hi, I'm trying to query for a field that takes ObjectId as value. I've tried the following but to no avail:

const ObjectID = require('mongodb').ObjectID

and then

return this.findByFields({album_id: new ObjectID('someidhere')})

Are ObjectIds supported in findByFields()? How should I pass them?

thanks!

lorensr commented 3 years ago

That should work—I just added a test case that looks like it covers it:

5d7348b

It's passing, but if you can modify it to get it to fail, or add a new one that covers your case, I can fix it!

tubbo commented 3 years ago

I think there may be something wrong with the mocks used in cache.test.js. I wrote a test in that file to see whether a field not named _id will work as an ObjectID:

diff --git a/src/__tests__/cache.test.js b/src/__tests__/cache.test.js
index c4a98a0..5204236 100644
--- a/src/__tests__/cache.test.js
+++ b/src/__tests__/cache.test.js
@@ -10,12 +10,13 @@ import {
 } from '../cache'

 const hexId = '5cf82e14a220a607eb64a7d4'
-
+const relation = '60ccce22a1ca48a0d0197159'
 const docs = {
   one: {
     _id: ObjectId(hexId),
     foo: 'bar',
-    tags: ['foo', 'bar']
+    tags: ['foo', 'bar'],
+    relation: ObjectId(relation)
   },
   two: {
     _id: ObjectId(),
@@ -161,6 +162,14 @@ describe('createCachingMethods', () => {
     expect(collection.find.mock.calls.length).toBe(1)
   })

+  it('finds by ObjectID reference', async () => {
+    const foundDocs = await api.findByFields({ relation: ObjectId(relation) })
+
+    expect(foundDocs[0]).toBe(docs.one)
+    expect(foundDocs.length).toBe(1)
+    expect(collection.find.mock.calls.length).toBe(1)
+  })
+
   it('finds by array field', async () => {
     const foundDocs = await api.findByFields({ tags: 'bar' })

This passes, but when I actually write a test using a real database, I can't seem to access fields using an ObjectID:

import { MongoDataSource } from 'apollo-datasource-mongodb'
import { ObjectId } from 'mongodb'

import { Room, Maybe } from '../generated'
import { ResolverContext } from '../context'

class Rooms extends MongoDataSource<Room, ResolverContext> {
  async getRoom(id: string): Promise<Maybe<Room>> {
    const data = await this.findOneById(id)

    if (!data) return null

    return data
  }

  async inCommunity(id: ObjectId): Promise<Room[]> {
    const data = await this.findByFields({ community: id })

    if (!data) return []

    return data as Room[]
  }
}

export default Rooms
import mongoose from 'mongoose'
import Rooms from '../rooms'
import { setupTest, teardownTest } from '../../../../testHelper'

describe('Rooms', () => {
  beforeEach(setupTest)
  afterEach(teardownTest)

  it('finds rooms in the community', async () => {
    const db = mongoose.connections[0].getClient().db()
    const {
      ops: [user],
    } = await db.collection('users').insertOne({
      username: 'user',
    })
    const {
      ops: [community],
    } = await db.collection('communities').insertOne({
      name: 'foos',
      leader: user._id,
    })
    const {
      ops: [room],
    } = await db.collection('rooms').insertOne({
      name: '#general',
      community: community._id,
    })
    const rooms = new Rooms(db.collection('rooms'))
    rooms.initialize({})
    const [result] = await rooms.inCommunity(community._id)

    expect(result).toBeDefined()
    expect(result).not.toBeNull()
    expect(result?.name).toEqual(room.name)
  })
})

I get this output from Jest:

  ● Rooms › finds rooms in the community

    expect(received).toBeDefined()

    Received: undefined

      30 |     const [result] = await rooms.inCommunity(community._id)
      31 |
    > 32 |     expect(result).toBeDefined()
         |                    ^
      33 |     expect(result).not.toBeNull()
      34 |     expect(result?.name).toEqual(room.name)
      35 |   })

      at Object.<anonymous> (src/http/graphql/data-sources/__tests__/rooms.test.ts:32:20