graphql-compose / graphql-compose-mongoose

Mongoose model converter to GraphQL types with resolvers for graphql-compose https://github.com/nodkz/graphql-compose
MIT License
708 stars 94 forks source link

searching in Array of elements cause a search by position by default #388

Open jmtt89 opened 2 years ago

jmtt89 commented 2 years ago

I am trying to use "$in" to search for elements in array, but I noticed the schema is searching by position in the array and only match the first parameter

turning up the debug flag on mongoose:

// app.js
...
mongoose.set('debug', true)
...
const schema = require('./schema')

const graphql = graphqlHTTP(async (req) => ({
    schema: schema,
    context: () => context(req),
}))

This is the gql query:

query getTemplates{
  Pagination(filter:{tags: ["616468c6859647275b2e41c9", "616468c8859647275b2e41cf"]}){
    count
    items{
      _id
    }
  }
}

And the Console print this

Mongoose: templates.countDocuments({ 'tags.0': '616468c6859647275b2e41c9', 'tags.1': '616468c8859647275b2e41cf', tags: { '$in': [ '616468c6859647275b2e41c9', '616468c8859647275b2e41cf' ] }}, {})
Mongoose: templates.find({ 'tags.0': '616468c6859647275b2e41c9', 'tags.1': '616468c8859647275b2e41cf', tags: { '$in': [ '616468c6859647275b2e41c9', '616468c8859647275b2e41cf' ] }}, { limit: 21, projection: { count: true, 'items._id': true, _id: true }})

I think the problem is the filter is trying to set a absolute match of array position ('tags.0' , 'tags.1' .... 'tags.X' ) it is possible to change that behavior configuring something in scheme or somewhere else?

This is the code for each file:

// model.js
'use strict'

const { model, Schema } = require('mongoose')
const { composeMongoose } = require('graphql-compose-mongoose')

const schema = new Schema(
    {
        tags: [String],
        text: {
            type: String,
            text: true,
        },
        global: {
            type: Boolean,
            default: false,
        },
    },
    {
        timestamps: true,
    }
)

const options = {
    inputType: {
        removeFields: ['createdAt', 'updatedAt', 'global'],
    },
}

const Template = model('Template', schema)
module.exports = {
    Model: Template,
    TypeComposer: composeMongoose(Template, options),
}
// template-schema,js
'use strict'

const { TypeComposer, Model } = require('../models/template/model')

const Query = {
    ById: TypeComposer.mongooseResolvers.findById(),
    ByIds: TypeComposer.mongooseResolvers.findByIds(),
    One: TypeComposer.mongooseResolvers.findOne(),
    Many: TypeComposer.mongooseResolvers.findMany(),
    DataLoader: TypeComposer.mongooseResolvers.dataLoader(),
    DataLoaderMany: TypeComposer.mongooseResolvers.dataLoaderMany(),
    Count: TypeComposer.mongooseResolvers.count(),
    Connection: TypeComposer.mongooseResolvers.connection(),
    Pagination: TypeComposer.mongooseResolvers
        .pagination()
        .addFilterArg({
            name: 'search',
            type: 'String',
            query: (query, value, resolveParams) => {
                resolveParams.args.sort = {
                    score: { $meta: 'textScore' },
                }
                query.$text = { $search: value }
                resolveParams.projection.score = { $meta: 'textScore' }
            },
        })
        .addFilterArg({
            name: 'tags',
            type: '[String]',
            description: 'Search by $in operator',
            query: (rawQuery, value) => {
                console.log('tags', { rawQuery, value })
                rawQuery.tags = { $in: value }
                console.log(rawQuery)
            },
        }),
}

const Mutation = {
    CreateOne: TypeComposer.mongooseResolvers.createOne(),
    CreateMany: TypeComposer.mongooseResolvers.createMany(),
    UpdateById: TypeComposer.mongooseResolvers.updateById(),
    UpdateOne: TypeComposer.mongooseResolvers.updateOne(),
    UpdateMany: TypeComposer.mongooseResolvers.updateMany(),
    RemoveById: TypeComposer.mongooseResolvers.removeById(),
    RemoveOne: TypeComposer.mongooseResolvers.removeOne(),
    RemoveMany: TypeComposer.mongooseResolvers.removeMany()
}

module.exports = { Query, Mutation }
// index.js
'use strict'

const { schemaComposer } = require('graphql-compose')
const TemplateEmail = require('./template-schema')

schemaComposer.Query.addFields({
    ...Template.Query
})

schemaComposer.Mutation.addFields({
    ...Template.Mutation,
})

module.exports = schemaComposer.buildSchema()
zenhuw commented 7 months ago

Hi, did you resolve this problem?