{"id":13564211,"url":"https://github.com/graphql-compose/graphql-compose-mongoose","last_synced_at":"2025-05-15T08:05:44.774Z","repository":{"id":39615484,"uuid":"60606045","full_name":"graphql-compose/graphql-compose-mongoose","owner":"graphql-compose","description":"Mongoose model converter to GraphQL types with resolvers for graphql-compose https://github.com/nodkz/graphql-compose","archived":false,"fork":false,"pushed_at":"2023-11-15T00:53:44.000Z","size":3436,"stargazers_count":708,"open_issues_count":128,"forks_count":94,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-05-11T16:28:51.794Z","etag":null,"topics":["graphql","graphql-compose","graphql-compose-plugin","graphql-types","hacktoberfest","mongoose","schema-builder"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/graphql-compose.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":["nodkz"],"patreon":null,"open_collective":"graphql-compose","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2016-06-07T10:52:39.000Z","updated_at":"2025-02-13T04:15:30.000Z","dependencies_parsed_at":"2024-01-11T22:00:07.515Z","dependency_job_id":"b0efd1d6-c4b0-48b2-818c-7253a810768e","html_url":"https://github.com/graphql-compose/graphql-compose-mongoose","commit_stats":{"total_commits":582,"total_committers":42,"mean_commits":"13.857142857142858","dds":0.4862542955326461,"last_synced_commit":"05ccdf088d303b258ff2af7cc2794781444aec79"},"previous_names":["nodkz/graphql-compose-mongoose"],"tags_count":156,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql-compose%2Fgraphql-compose-mongoose","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql-compose%2Fgraphql-compose-mongoose/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql-compose%2Fgraphql-compose-mongoose/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql-compose%2Fgraphql-compose-mongoose/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/graphql-compose","download_url":"https://codeload.github.com/graphql-compose/graphql-compose-mongoose/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254190419,"owners_count":22029639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","graphql-compose","graphql-compose-plugin","graphql-types","hacktoberfest","mongoose","schema-builder"],"created_at":"2024-08-01T13:01:28.068Z","updated_at":"2025-05-15T08:05:44.720Z","avatar_url":"https://github.com/graphql-compose.png","language":"TypeScript","readme":"# graphql-compose-mongoose\n\n[![travis build](https://img.shields.io/travis/graphql-compose/graphql-compose-mongoose.svg)](https://travis-ci.org/graphql-compose/graphql-compose-mongoose)\n[![codecov coverage](https://img.shields.io/codecov/c/github/graphql-compose/graphql-compose-mongoose.svg)](https://codecov.io/github/graphql-compose/graphql-compose-mongoose)\n[![npm](https://img.shields.io/npm/v/graphql-compose-mongoose.svg)](https://www.npmjs.com/package/graphql-compose-mongoose)\n[![trends](https://img.shields.io/npm/dt/graphql-compose-mongoose.svg)](http://www.npmtrends.com/graphql-compose-mongoose)\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n[![Backers on Open Collective](https://opencollective.com/graphql-compose/backers/badge.svg)](#backers)\n[![Sponsors on Open Collective](https://opencollective.com/graphql-compose/sponsors/badge.svg)](#sponsors)\n\nThis is a plugin for [graphql-compose](https://github.com/graphql-compose/graphql-compose), which derives GraphQLType from your [mongoose model](https://github.com/Automattic/mongoose). Also derives bunch of internal GraphQL Types. Provide all CRUD resolvers, including `graphql connection`, also provided basic search via operators ($lt, $gt and so on).\n\n[Release Notes for v9.0.0](https://github.com/graphql-compose/graphql-compose-mongoose/blob/alpha/docs/releases/9.0.0.md) contains a lot of improvements. It's strongly recommended for reading before upgrading from v8.\n\n\u003c!-- TOC depthFrom:2 --\u003e\n\n- [Installation](#installation)\n- [Intro video](#intro-video)\n- [Example](#example)\n  - [Working with Mongoose Collection Level Discriminators](#working-with-mongoose-collection-level-discriminators)\n- [Customization options](#customization-options)\n  - [`composeMongoose` customization options](#composemongoose-customization-options)\n- [Resolvers' customization options](#resolvers-customization-options)\n  - [`connection(opts?: ConnectionResolverOpts)`](#connectionopts-connectionresolveropts)\n  - [`count(opts?: CountResolverOpts)`](#countopts-countresolveropts)\n  - [`createMany(opts?: CreateManyResolverOpts)`](#createmanyopts-createmanyresolveropts)\n  - [`createOne(opts?: CreateOneResolverOpts)`](#createoneopts-createoneresolveropts)\n  - [`dataLoader(opts?: DataLoaderResolverOpts)`](#dataloaderopts-dataloaderresolveropts)\n  - [`dataLoaderMany(opts?: DataLoaderManyResolverOpts)`](#dataloadermanyopts-dataloadermanyresolveropts)\n  - [`findById(opts?: FindByIdResolverOpts)`](#findbyidopts-findbyidresolveropts)\n  - [`findByIds(opts?: FindByIdsResolverOpts)`](#findbyidsopts-findbyidsresolveropts)\n  - [`findMany(opts?: FindManyResolverOpts)`](#findmanyopts-findmanyresolveropts)\n  - [`findOne(opts?: FindOneResolverOpts)`](#findoneopts-findoneresolveropts)\n  - [`pagination(opts?: PaginationResolverOpts)`](#paginationopts-paginationresolveropts)\n  - [`removeById(opts?: RemoveByIdResolverOpts)`](#removebyidopts-removebyidresolveropts)\n  - [`removeMany(opts?: RemoveManyResolverOpts)`](#removemanyopts-removemanyresolveropts)\n  - [`removeOne(opts?: RemoveOneResolverOpts)`](#removeoneopts-removeoneresolveropts)\n  - [`updateById(opts?: UpdateByIdResolverOpts)`](#updatebyidopts-updatebyidresolveropts)\n  - [`updateMany(opts?: UpdateManyResolverOpts)`](#updatemanyopts-updatemanyresolveropts)\n  - [`updateOne(opts?: UpdateOneResolverOpts)`](#updateoneopts-updateoneresolveropts)\n  - [Description of common resolvers' options](#description-of-common-resolvers-options)\n    - [`FilterHelperArgsOpts`](#filterhelperargsopts)\n    - [`SortHelperArgsOpts`](#sorthelperargsopts)\n    - [`RecordHelperArgsOpts`](#recordhelperargsopts)\n    - [`LimitHelperArgsOpts`](#limithelperargsopts)\n- [FAQ](#faq)\n  - [Can I get generated vanilla GraphQL types?](#can-i-get-generated-vanilla-graphql-types)\n  - [How to add custom fields?](#how-to-add-custom-fields)\n  - [How to build nesting/relations?](#how-to-build-nestingrelations)\n  - [Reusing the same mongoose Schema in embedded object fields](#reusing-the-same-mongoose-schema-in-embedded-object-fields)\n  - [Access and modify mongoose doc before save](#access-and-modify-mongoose-doc-before-save)\n  - [How can I restrict access to certain fields or documents?](#how-can-i-restrict-access-to-certain-fields-or-documents)\n  - [How can I push/pop or add/remove values to arrays?](#how-can-i-pushpop-or-addremove-values-to-arrays)\n  - [Is it possible to use several schemas?](#is-it-possible-to-use-several-schemas)\n  - [Embedded documents has `_id` field and you don't need it?](#embedded-documents-has-_id-field-and-you-dont-need-it)\n  - [Can field name in schema have different name in database?](#can-field-name-in-schema-have-different-name-in-database)\n- [Backers](#backers)\n- [Sponsors](#sponsors)\n- [License](#license)\n\n\u003c!-- /TOC --\u003e\n\n## Installation\n\n```bash\nnpm install graphql graphql-compose mongoose graphql-compose-mongoose --save\n```\n\nModules `graphql`, `graphql-compose`, `mongoose` are in `peerDependencies`, so should be installed explicitly in your app. They have global objects and should not have ability to be installed as submodule.\n\n## Intro video\n\nViktor Kjartansson created a quite solid intro for `graphql-compose-mongoose` in comparison with `graphql-tools`:\n\n\u003ca href=\"https://www.youtube.com/watch?v=RXcY-OoGnQ8\" target=\"_blank\"\u003e\u003cimg src=\"https://img.youtube.com/vi/RXcY-OoGnQ8/0.jpg\" alt=\"#2 Mongoose - add GraphQL with graphql-compose\" style=\"width: 380px\" /\u003e\n\n\u003chttps://www.youtube.com/watch?v=RXcY-OoGnQ8\u003e (23 mins)\n\n## Example\n\nLive demo: \u003chttps://graphql-compose.herokuapp.com/\u003e\n\nSource code: \u003chttps://github.com/graphql-compose/graphql-compose-examples\u003e\n\nSmall explanation for variables naming:\n\n- `UserSchema` - this is a mongoose schema\n- `User` - this is a mongoose model\n- `UserTC` - this is a `ObjectTypeComposer` instance for User. `ObjectTypeComposer` has `GraphQLObjectType` inside, available via method `UserTC.getType()`.\n- Here and in all other places of code variables suffix `...TC` means that this is `ObjectTypeComposer` instance, `...ITC` - `InputTypeComposer`, `...ETC` - `EnumTypeComposer`.\n\n```ts\nimport mongoose from 'mongoose';\nimport { composeMongoose } from 'graphql-compose-mongoose';\nimport { schemaComposer } from 'graphql-compose';\n\n// STEP 1: DEFINE MONGOOSE SCHEMA AND MODEL\nconst LanguagesSchema = new mongoose.Schema({\n  language: String,\n  skill: {\n    type: String,\n    enum: ['basic', 'fluent', 'native'],\n  },\n});\n\nconst UserSchema = new mongoose.Schema({\n  name: String, // standard types\n  age: {\n    type: Number,\n    index: true,\n  },\n  ln: {\n    type: [LanguagesSchema], // you may include other schemas (here included as array of embedded documents)\n    default: [],\n    alias: 'languages', // in schema `ln` will be named as `languages`\n  },\n  contacts: { // another mongoose way for providing embedded documents\n    email: String,\n    phones: [String], // array of strings\n  },\n  gender: { // enum field with values\n    type: String,\n    enum: ['male', 'female'],\n  },\n  someMixed: {\n    type: mongoose.Schema.Types.Mixed,\n    description: 'Can be any mixed type, that will be treated as JSON GraphQL Scalar Type',\n  },\n});\nconst User = mongoose.model('User', UserSchema);\n\n// STEP 2: CONVERT MONGOOSE MODEL TO GraphQL PIECES\nconst customizationOptions = {}; // left it empty for simplicity, described below\nconst UserTC = composeMongoose(User, customizationOptions);\n\n// STEP 3: ADD NEEDED CRUD USER OPERATIONS TO THE GraphQL SCHEMA\n// via graphql-compose it will be much much easier, with less typing\nschemaComposer.Query.addFields({\n  userById: UserTC.mongooseResolvers.findById(),\n  userByIds: UserTC.mongooseResolvers.findByIds(),\n  userOne: UserTC.mongooseResolvers.findOne(),\n  userMany: UserTC.mongooseResolvers.findMany(),\n  userDataLoader: UserTC.mongooseResolvers.dataLoader(),\n  userDataLoaderMany: UserTC.mongooseResolvers.dataLoaderMany(),\n  userByIdLean: UserTC.mongooseResolvers.findById({ lean: true }),\n  userByIdsLean: UserTC.mongooseResolvers.findByIds({ lean: true }),\n  userOneLean: UserTC.mongooseResolvers.findOne({ lean: true }),\n  userManyLean: UserTC.mongooseResolvers.findMany({ lean: true }),\n  userDataLoaderLean: UserTC.mongooseResolvers.dataLoader({ lean: true }),\n  userDataLoaderManyLean: UserTC.mongooseResolvers.dataLoaderMany({ lean: true }),\n  userCount: UserTC.mongooseResolvers.count(),\n  userConnection: UserTC.mongooseResolvers.connection(),\n  userPagination: UserTC.mongooseResolvers.pagination(),\n});\n\nschemaComposer.Mutation.addFields({\n  userCreateOne: UserTC.mongooseResolvers.createOne(),\n  userCreateMany: UserTC.mongooseResolvers.createMany(),\n  userUpdateById: UserTC.mongooseResolvers.updateById(),\n  userUpdateOne: UserTC.mongooseResolvers.updateOne(),\n  userUpdateMany: UserTC.mongooseResolvers.updateMany(),\n  userRemoveById: UserTC.mongooseResolvers.removeById(),\n  userRemoveOne: UserTC.mongooseResolvers.removeOne(),\n  userRemoveMany: UserTC.mongooseResolvers.removeMany(),\n});\n\n// STEP 4: BUILD GraphQL SCHEMA OBJECT\nconst schema = schemaComposer.buildSchema();\nexport default schema;\n\n// STEP 5: DEMO USE OF GraphQL SCHEMA OBJECT\n// Just a demo, normally you'd pass schema object to server such as Apollo server.\nimport { graphql } from 'graphql';\n\n(async () =\u003e {\n  await mongoose.connect('mongodb://localhost:27017/test');\n  await mongoose.connection.dropDatabase();\n\n  await User.create({ name: 'alice', age: 29, gender: 'female' });\n  await User.create({ name: 'maria', age: 31, gender: 'female' });\n  const bob = await User.create({ name: 'bob', age: 30, gender: 'male' });\n\n  const response1 = await graphql({\n    schema,\n    source: 'query { userMany { _id name } }',\n  });\n  console.dir(response1, { depth: 5 });\n\n  const response2 = await graphql({\n    schema,\n    source: 'query($id: MongoID!) { userById(_id: $id) { _id name } }',\n    variableValues: { id: bob._id },\n  });\n  console.dir(response2, { depth: 5 });\n\n  const response3 = await graphql({\n    schema,\n    source: 'mutation($id: MongoID!, $name: String) { userUpdateOne(filter: {_id: $id}, record: { name: $name }) { record { _id name } } }',\n    variableValues: { id: bob._id, name: 'bill' },\n  });\n  console.dir(response3, { depth: 5 });\n\n  mongoose.disconnect();\n})();\n```\n\nThat's all!\nYou think that is to much code?\nI don't think so, because by default internally was created about 55 graphql types (for input, sorting, filtering). So you will need much much more lines of code to implement all these CRUD operations by hands.\n\n### Working with Mongoose Collection Level Discriminators\n\nVariable Namings\n\n- `...DTC` - Suffix for a `DiscriminatorTypeComposer` instance, which is also an instance of `ObjectTypeComposer`. All fields and Relations manipulations on this instance affects all registered discriminators and the Discriminator Interface.\n\n```ts\n  import mongoose from 'mongoose';\n  import { schemaComposer } from 'graphql-compose';\n  import { composeMongooseDiscriminators } from 'graphql-compose-mongoose';\n\n  // pick a discriminatorKey\n  const DKey = 'type';\n\n  const enumCharacterType = {\n    PERSON: 'Person',\n    DROID: 'Droid',\n  };\n\n  // DEFINE BASE SCHEMA\n  const CharacterSchema = new mongoose.Schema({\n    // _id: field...\n    type: {\n      type: String,\n      required: true,\n      enum: (Object.keys(enumCharacterType): Array\u003cstring\u003e),\n      description: 'Character type Droid or Person',\n    },\n\n    name: String,\n    height: Number,\n    mass: Number,\n    films: [String],\n  });\n\n  // DEFINE DISCRIMINATOR SCHEMAS\n  const DroidSchema = new mongoose.Schema({\n    makeDate: String,\n    primaryFunction: [String],\n  });\n\n  const PersonSchema = new mongoose.Schema({\n    gender: String,\n    hairColor: String,\n    starships: [String],\n  });\n\n  // set discriminator Key\n  CharacterSchema.set('discriminatorKey', DKey);\n\n  // create base Model\n  const CharacterModel = mongoose.model('Character', CharacterSchema);\n\n  // create mongoose discriminator models\n  const DroidModel = CharacterModel.discriminator(enumCharacterType.DROID, DroidSchema);\n  const PersonModel = CharacterModel.discriminator(enumCharacterType.PERSON, PersonSchema);\n\n  // create DiscriminatorTypeComposer\n  const baseOptions = { // regular TypeConverterOptions, passed to composeMongoose\n    fields: {\n      remove: ['friends'],\n    }\n  }\n  const CharacterDTC = composeMongooseDiscriminators(CharacterModel, baseOptions);\n\n  // create Discriminator Types\n  const droidTypeConverterOptions = {  // this options will be merged with baseOptions -\u003e customizationsOptions\n    fields: {\n      remove: ['makeDate'],\n    }\n  };\n  const DroidTC = CharacterDTC.discriminator(DroidModel, droidTypeConverterOptions);\n  const PersonTC = CharacterDTC.discriminator(PersonModel);  // baseOptions -\u003e customizationsOptions applied\n\n  // You may now use CharacterDTC to add fields to all Discriminators\n  // Use DroidTC, `PersonTC as any other ObjectTypeComposer.\n  schemaComposer.Mutation.addFields({\n    droidCreate: DroidTC.getResolver('createOne'),\n    personCreate: PersonTC.getResolver('createOne'),\n  });\n\n  const schema = schemaComposer.buildSchema();\n\n  describe('createOne', () =\u003e {\n    it('should create child document without specifying DKey', async () =\u003e {\n      const res = await graphql.graphql({\n        schema,\n        source: `mutation CreateCharacters {\n          droidCreate(record: {name: \"Queue XL\", modelNumber: 360 }) {\n            record {\n              __typename\n              type\n              name\n              modelNumber\n            }\n          }\n\n          personCreate(record: {name: \"mernxl\", dob: 57275272}) {\n            record {\n              __typename\n              type\n              name\n              dob\n            }\n          }\n        }`\n      );\n\n      expect(res).toEqual({\n        data: {\n          droidCreate: {\n            record: { __typename: 'Droid', type: 'Droid', name: 'Queue XL', modelNumber: 360 },\n          },\n          personCreate: {\n            record: { __typename: 'Person', type: 'Person', name: 'mernxl', dob: 57275272 },\n          },\n        },\n      });\n    });\n  });\n```\n\n## Customization options\n\n### `composeMongoose` customization options\n\nWhen you converting mongoose model `const UserTC = composeMongoose(User, opts: ComposeMongooseOpts);` you may tune every piece of future derived types – setup name and description for the main type, remove fields or leave only desired fields.\n\n```ts\ntype ComposeMongooseOpts = {\n  /**\n   * Which type registry use for generated types.\n   * By default is used global default registry.\n   */\n  schemaComposer?: SchemaComposer\u003cTContext\u003e;\n  /**\n   * What should be base type name for generated type from mongoose model.\n   */\n  name?: string;\n  /**\n   * Provide arbitrary description for generated type.\n   */\n  description?: string;\n  /**\n   * You can leave only whitelisted fields in type via this option.\n   * Any other fields will be removed.\n   */\n  onlyFields?: string[];\n  /**\n   * You can remove some fields from type via this option.\n   */\n  removeFields?: string[];\n  /**\n   * You may configure generated InputType\n   */\n  inputType?: TypeConverterInputTypeOpts;\n  /**\n   * You can make fields as NonNull if they have default value in mongoose model.\n   */\n  defaultsAsNonNull?: boolean;\n};\n```\n\nThis is `opts.inputType` options for default InputTypeObject which will be provided to all resolvers for `filter` and `input` args.\n\n```ts\ntype TypeConverterInputTypeOpts = {\n  /**\n   * What should be input type name.\n   * By default: baseTypeName + 'Input'\n   */\n  name?: string;\n  /**\n   * Provide arbitrary description for generated type.\n   */\n  description?: string;\n  /**\n   * You can leave only whitelisted fields in type via this option.\n   * Any other fields will be removed.\n   */\n  onlyFields?: string[];\n  /**\n   * You can remove some fields from type via this option.\n   */\n  removeFields?: string[];\n  /**\n   * This option makes provided fieldNames as required\n   */\n  requiredFields?: string[];\n};\n```\n\n## Resolvers' customization options\n\nWhen you are creating resolvers from `mongooseResolvers` factory, you may provide customizationOptions to it:\n\n```ts\nUserTC.mongooseResolvers.findMany(opts);\n```\n\n### `connection(opts?: ConnectionResolverOpts)`\n\n```ts\ntype ConnectionResolverOpts\u003cTContext = any\u003e = {\n  /** See below **/\n  sort?: ConnectionSortMapOpts;\n  name?: string;\n  defaultLimit?: number | undefined;\n  edgeTypeName?: string;\n  edgeFields?: ObjectTypeComposerFieldConfigMap\u003cany, TContext\u003e;\n  /** See below **/\n  countOpts?: CountResolverOpts;\n  /** See below **/\n  findManyOpts?: FindManyResolverOpts;\n}\n```\n\nThe `countOpts` and `findManyOpts` props would be used to customize the internally created `findMany` and `count` resolver factories used by the connection resolver.\nIf not provided the default configuration for each of the resolver factories is assumed.\n\nThe `sort` prop is optional. When provided it is used to customize the sorting behaviour of the connection. When not provided, the sorting configuration is derived from the existing indexes on the model.\n\nPlease refer to the documentation of the [graphql-compose-connection](https://github.com/graphql-compose/graphql-compose-connection) plugin for more details on the sorting customization parameter.\n\n\n\n### `count(opts?: CountResolverOpts)`\n\n```ts\ninterface CountResolverOpts {\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `filter` argument. If `false` then arg will be removed. */\n  filter?: FilterHelperArgsOpts | false;\n}\n```\n\n### `createMany(opts?: CreateManyResolverOpts)`\n\n```ts\ninterface CreateManyResolverOpts {\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `records` argument. */\n  records?: RecordHelperArgsOpts;\n  /** Customize payload.recordIds field. If false, then this field will be removed. */\n  recordIds?: PayloadRecordIdsHelperOpts | false;\n  /** Customize payload.error field. If true, then this field will be removed. */\n  disableErrorField?: boolean;\n}\n```\n\n### `createOne(opts?: CreateOneResolverOpts)`\n\n```ts\ninterface CreateOneResolverOpts {\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `record` argument */\n  record?: RecordHelperArgsOpts;\n  /** Customize payload.recordId field. If false, then this field will be removed. */\n  recordId?: PayloadRecordIdHelperOpts | false;\n  /** Customize payload.error field. If true, then this field will be removed. */\n  disableErrorField?: boolean;\n}\n```\n\n### `dataLoader(opts?: DataLoaderResolverOpts)`\n\n```ts\ninterface DataLoaderResolverOpts {\n  /**\n   * Enabling the lean option tells Mongoose to skip instantiating\n   * a full Mongoose document and just give you the plain JavaScript objects.\n   * Documents are much heavier than vanilla JavaScript objects,\n   * because they have a lot of internal state for change tracking.\n   * The downside of enabling lean is that lean docs don't have:\n   *   Default values\n   *   Getters and setters\n   *   Virtuals\n   * Read more about `lean`: https://mongoosejs.com/docs/tutorials/lean.html\n   */\n  lean?: boolean;\n}\n```\n\n### `dataLoaderMany(opts?: DataLoaderManyResolverOpts)`\n\n```ts\ninterface DataLoaderManyResolverOpts {\n  /**\n   * Enabling the lean option tells Mongoose to skip instantiating\n   * a full Mongoose document and just give you the plain JavaScript objects.\n   * Documents are much heavier than vanilla JavaScript objects,\n   * because they have a lot of internal state for change tracking.\n   * The downside of enabling lean is that lean docs don't have:\n   *   Default values\n   *   Getters and setters\n   *   Virtuals\n   * Read more about `lean`: https://mongoosejs.com/docs/tutorials/lean.html\n   */\n  lean?: boolean;\n}\n```\n\n### `findById(opts?: FindByIdResolverOpts)`\n\n```ts\ninterface FindByIdResolverOpts {\n  /**\n   * Enabling the lean option tells Mongoose to skip instantiating\n   * a full Mongoose document and just give you the plain JavaScript objects.\n   * Documents are much heavier than vanilla JavaScript objects,\n   * because they have a lot of internal state for change tracking.\n   * The downside of enabling lean is that lean docs don't have:\n   *   Default values\n   *   Getters and setters\n   *   Virtuals\n   * Read more about `lean`: https://mongoosejs.com/docs/tutorials/lean.html\n   */\n  lean?: boolean;\n}\n```\n\n### `findByIds(opts?: FindByIdsResolverOpts)`\n\n```ts\ninterface FindByIdsResolverOpts {\n  /**\n   * Enabling the lean option tells Mongoose to skip instantiating\n   * a full Mongoose document and just give you the plain JavaScript objects.\n   * Documents are much heavier than vanilla JavaScript objects,\n   * because they have a lot of internal state for change tracking.\n   * The downside of enabling lean is that lean docs don't have:\n   *   Default values\n   *   Getters and setters\n   *   Virtuals\n   * Read more about `lean`: https://mongoosejs.com/docs/tutorials/lean.html\n   */\n  lean?: boolean;\n  limit?: LimitHelperArgsOpts | false;\n  sort?: SortHelperArgsOpts | false;\n}\n```\n\n### `findMany(opts?: FindManyResolverOpts)`\n\n```ts\ninterface FindManyResolverOpts {\n  /**\n   * Enabling the lean option tells Mongoose to skip instantiating\n   * a full Mongoose document and just give you the plain JavaScript objects.\n   * Documents are much heavier than vanilla JavaScript objects,\n   * because they have a lot of internal state for change tracking.\n   * The downside of enabling lean is that lean docs don't have:\n   *   Default values\n   *   Getters and setters\n   *   Virtuals\n   * Read more about `lean`: https://mongoosejs.com/docs/tutorials/lean.html\n   */\n  lean?: boolean;\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `filter` argument. If `false` then arg will be removed. */\n  filter?: FilterHelperArgsOpts | false;\n  sort?: SortHelperArgsOpts | false;\n  limit?: LimitHelperArgsOpts | false;\n  skip?: false;\n}\n```\n\n### `findOne(opts?: FindOneResolverOpts)`\n\n```ts\ninterface FindOneResolverOpts {\n  /**\n   * Enabling the lean option tells Mongoose to skip instantiating\n   * a full Mongoose document and just give you the plain JavaScript objects.\n   * Documents are much heavier than vanilla JavaScript objects,\n   * because they have a lot of internal state for change tracking.\n   * The downside of enabling lean is that lean docs don't have:\n   *   Default values\n   *   Getters and setters\n   *   Virtuals\n   * Read more about `lean`: https://mongoosejs.com/docs/tutorials/lean.html\n   */\n  lean?: boolean;\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `filter` argument. If `false` then arg will be removed. */\n  filter?: FilterHelperArgsOpts | false;\n  sort?: SortHelperArgsOpts | false;\n  skip?: false;\n}\n```\n\n### `pagination(opts?: PaginationResolverOpts)`\n\n```ts\ninterface PaginationResolverOpts {\n  name?: string;\n  perPage?: number;\n  countOpts?: CountResolverOpts;\n  findManyOpts?: FindManyResolverOpts;\n}\n```\n\n### `removeById(opts?: RemoveByIdResolverOpts)`\n\n```ts\ninterface RemoveByIdResolverOpts {\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize payload.recordId field. If false, then this field will be removed. */\n  recordId?: PayloadRecordIdHelperOpts | false;\n  /** Customize payload.error field. If true, then this field will be removed. */\n  disableErrorField?: boolean;\n}\n```\n\n### `removeMany(opts?: RemoveManyResolverOpts)`\n\n```ts\ninterface RemoveManyResolverOpts {\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `filter` argument. If `false` then arg will be removed. */\n  filter?: FilterHelperArgsOpts | false;\n  limit?: LimitHelperArgsOpts | false;\n  /** Customize payload.error field. If true, then this field will be removed. */\n  disableErrorField?: boolean;\n}\n```\n\n### `removeOne(opts?: RemoveOneResolverOpts)`\n\n```ts\ninterface RemoveOneResolverOpts {\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `filter` argument. If `false` then arg will be removed. */\n  filter?: FilterHelperArgsOpts | false;\n  sort?: SortHelperArgsOpts | false;\n  /** Customize payload.recordId field. If false, then this field will be removed. */\n  recordId?: PayloadRecordIdHelperOpts | false;\n  /** Customize payload.error field. If true, then this field will be removed. */\n  disableErrorField?: boolean;\n}\n```\n\n### `updateById(opts?: UpdateByIdResolverOpts)`\n\n```ts\ninterface UpdateByIdResolverOpts {\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `record` argument. */\n  record?: RecordHelperArgsOpts;\n  /** Customize payload.recordId field. If false, then this field will be removed. */\n  recordId?: PayloadRecordIdHelperOpts | false;\n  /** Customize payload.error field. If true, then this field will be removed. */\n  disableErrorField?: boolean;\n}\n```\n\n### `updateMany(opts?: UpdateManyResolverOpts)`\n\n```ts\ninterface UpdateManyResolverOpts {\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `record` argument. */\n  record?: RecordHelperArgsOpts;\n  /** Customize input-type for `filter` argument. If `false` then arg will be removed. */\n  filter?: FilterHelperArgsOpts | false;\n  sort?: SortHelperArgsOpts | false;\n  limit?: LimitHelperArgsOpts | false;\n  skip?: false;\n  /** Customize payload.error field. If true, then this field will be removed. */\n  disableErrorField?: boolean;\n}\n```\n\n### `updateOne(opts?: UpdateOneResolverOpts)`\n\n```ts\ninterface UpdateOneResolverOpts {\n  /** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */\n  suffix?: string;\n  /** Customize input-type for `record` argument. */\n  record?: RecordHelperArgsOpts;\n  /** Customize input-type for `filter` argument. If `false` then arg will be removed. */\n  filter?: FilterHelperArgsOpts | false;\n  sort?: SortHelperArgsOpts | false;\n  skip?: false;\n  /** Customize payload.recordId field. If false, then this field will be removed. */\n  recordId?: PayloadRecordIdHelperOpts | false;\n  /** Customize payload.error field. If true, then this field will be removed. */\n  disableErrorField?: boolean;\n}\n```\n\n### Description of common resolvers' options\n\n#### `FilterHelperArgsOpts`\n\n```ts\ntype FilterHelperArgsOpts = {\n  /**\n   * Add to filter arg only that fields which are indexed.\n   * If false then all fields will be available for filtering.\n   * By default: true\n   */\n  onlyIndexed?: boolean;\n  /**\n   * You can remove some fields from type via this option.\n   */\n  removeFields?: string | string[];\n  /**\n   * This option makes provided fieldNames as required\n   */\n  requiredFields?: string | string[];\n  /**\n   * Customize operators filtering or disable it at all.\n   * By default, for performance reason, `graphql-compose-mongoose` generates operators\n   * *only for indexed* fields.\n   *\n   * BUT you may enable operators for all fields when creating resolver in the following way:\n   *   // enables all operators for all fields\n   *   operators: true,\n   * OR provide a more granular `operators` configuration to suit your needs:\n   *   operators: {\n   *     // for `age` field add just 3 operators\n   *     age: ['in', 'gt', 'lt'],\n   *     // for non-indexed `amount` field add all operators\n   *     amount: true,\n   *     // don't add this field to operators\n   *     indexedField: false,\n   *   }\n   *\n   * Available logic operators: AND, OR\n   * Available field operators: gt, gte, lt, lte, ne, in, nin, regex, exists\n   */\n  operators?: FieldsOperatorsConfig | false;\n  /**\n   * Make arg `filter` as required if this option is true.\n   */\n  isRequired?: boolean;\n  /**\n   * Base type name for generated filter argument.\n   */\n  baseTypeName?: string;\n  /**\n   * Provide custom prefix for Type name\n   */\n  prefix?: string;\n  /**\n   * Provide custom suffix for Type name\n   */\n  suffix?: string;\n};\n```\n\n#### `SortHelperArgsOpts`\n\n```ts\ntype SortHelperArgsOpts = {\n  /**\n   * Allow sort arg to be an array of enum values. Example [AGE_DESC, NAME_ASC, _ID_ASC].\n   * Note enum values will only ever be generated for *indexed fields*.\n   */\n  multi?: boolean;\n  /**\n   * This option set custom type name for generated sort argument.\n   */\n  sortTypeName?: string;\n};\n```\n\n#### `RecordHelperArgsOpts`\n\n```ts\ntype RecordHelperArgsOpts = {\n  /**\n   * You can remove some fields from type via this option.\n   */\n  removeFields?: string[];\n  /**\n   * This option makes provided fieldNames as required\n   */\n  requiredFields?: string[];\n  /**\n   * This option makes all fields nullable by default.\n   * May be overridden by `requiredFields` property\n   */\n  allFieldsNullable?: boolean;\n  /**\n   * Provide custom prefix for Type name\n   */\n  prefix?: string;\n  /**\n   * Provide custom suffix for Type name\n   */\n  suffix?: string;\n  /**\n   * Make arg `record` as required if this option is true.\n   */\n  isRequired?: boolean;\n};\n```\n\n#### `LimitHelperArgsOpts`\n\n```ts\ntype LimitHelperArgsOpts = {\n  /**\n   * Set limit for default number of returned records\n   * if it does not provided in query.\n   * By default: 100\n   */\n  defaultValue?: number;\n};\n```\n\n## FAQ\n\n### Can I get generated vanilla GraphQL types?\n\n```ts\nconst UserTC = composeMongoose(User);\nUserTC.getType(); // returns GraphQLObjectType\nUserTC.getInputType(); // returns GraphQLInputObjectType, eg. for args\nUserTC.get('languages').getType(); // get GraphQLObjectType for nested field\nUserTC.get('fieldWithNesting.subNesting').getType(); // get GraphQL type of deep nested field\n```\n\n### How to add custom fields?\n\n```ts\nUserTC.addFields({\n  lonLat: ObjectTypeComposer.create('type LonLat { lon: Float, lat: Float }'),\n  notice: 'String', // shorthand definition\n  noticeList: { // extended\n    type: '[String]', // String, Int, Float, Boolean, ID, Json\n    description: 'Array of notices',\n    resolve: (source, args, context, info) =\u003e 'some value',\n  },\n  bio: {\n    type: GraphQLString,\n    description: 'Providing vanilla GraphQL type'\n  }\n})\n```\n\n### How to build nesting/relations?\n\nSuppose you `User` model has `friendsIds` field with array of user ids. So let build some relations:\n\n```ts\nUserTC.addRelation(\n  'friends',\n  {\n    resolver: () =\u003e UserTC.mongooseResolvers.dataLoaderMany(),\n    prepareArgs: { // resolver `findByIds` has `_ids` arg, let provide value to it\n      _ids: (source) =\u003e source.friendsIds,\n    },\n    projection: { friendsIds: 1 }, // point fields in source object, which should be fetched from DB\n  }\n);\nUserTC.addRelation(\n  'adultFriendsWithSameGender',\n  {\n    resolver: () =\u003e UserTC.mongooseResolvers.findMany(),\n    prepareArgs: { // resolver `findMany` has `filter` arg, we may provide mongoose query to it\n      filter: (source) =\u003e ({\n        _operators : { // Applying criteria on fields which have\n                       // operators enabled for them (by default, indexed fields only)\n          _id : { in: source.friendsIds },\n          age: { gt: 21 }\n        },\n        gender: source.gender,\n      }),\n      limit: 10,\n    },\n    projection: { friendsIds: 1, gender: 1 }, // required fields from source object\n  }\n);\n```\n\n### Reusing the same mongoose Schema in embedded object fields\n\nSuppose you have a common structure you use as embedded object in multiple Schemas.\nAlso suppose you want the structure to have the same GraphQL type across all parent types.\n(For instance, to allow reuse of fragments for this type)\nHere are Schemas to demonstrate:\n\n```ts\nimport { Schema } from 'mongoose';\n\nconst ImageDataStructure = Schema({\n  url: String,\n  dimensions : {\n    width: Number,\n    height: Number\n  }\n}, { _id: false });\n\nconst UserProfile = Schema({\n  fullName: String,\n  personalImage: ImageDataStructure\n});\n\nconst Article = Schema({\n  title: String,\n  heroImage: ImageDataStructure\n});\n```\n\nIf you want the `ImageDataStructure` to use the same GraphQL type in both `Article` and `UserProfile` you will need create it as a mongoose schema (not a standard javascript object) and to explicitly tell `graphql-compose-mongoose` the name you want it to have. Otherwise, without the name, it would generate the name according to the first parent this type was embedded in.\n\nDo the following:\n\n```ts\nimport { schemaComposer } from 'graphql-compose'; // get the default schemaComposer or your created schemaComposer\nimport { convertSchemaToGraphQL } from 'graphql-compose-mongoose';\n\nconvertSchemaToGraphQL(ImageDataStructure, 'EmbeddedImage', schemaComposer); // Force this type on this mongoose schema\n```\n\nBefore continuing to convert your models to TypeComposers:\n\n```ts\nimport mongoose from 'mongoose';\nimport { composeMongoose } from 'graphql-compose-mongoose';\n\nconst UserProfile = mongoose.model('UserProfile', UserProfile);\nconst Article = mongoose.model('Article', Article);\n\nconst UserProfileTC = composeMongoose(UserProfile);\nconst ArticleTC = composeMongoose(Article);\n```\n\nThen, you can use queries like this:\n\n```graphql\nquery {\n  topUser {\n    fullName\n    personalImage {\n      ...fullImageData\n    }\n  }\n  topArticle {\n    title\n    heroImage {\n      ...fullImageData\n    }\n  }\n}\nfragment fullImageData on EmbeddedImage {\n  url\n  dimensions {\n    width height\n  }\n}\n```\n\n### Access and modify mongoose doc before save\n\nThis library provides some amount of ready resolvers for fetch and update data which was mentioned above. And you can [create your own resolver](https://github.com/graphql-compose/graphql-compose) of course. However you can find that add some actions or light modifications of mongoose document directly before save at existing resolvers appears more simple than create new resolver. Some of resolvers accepts *before save hook* which can be provided in *resolver params* as param named `beforeRecordMutate`. This hook allows to have access and modify mongoose document before save. The resolvers which supports this hook are:\n\n- createOne\n- createMany\n- removeById\n- removeOne\n- updateById\n- updateOne\n\nThe prototype of before save hook:\n\n```ts\n(doc: mixed, rp: ResolverResolveParams) =\u003e Promise\u003c*\u003e,\n```\n\nThe typical implementation may be like this:\n\n```ts\n// extend resolve params with hook\nrp.beforeRecordMutate = async function(doc, rp) {\n  doc.userTouchedAt = new Date();\n\n  const canMakeUpdate  = await performAsyncTask( ...provide data from doc... )\n  if (!canMakeUpdate) {\n    throw new Error('Forbidden!');\n  }\n\n  return doc;\n}\n```\n\nYou can provide your implementation directly in type composer:\n\n```ts\nUserTC.wrapResolverResolve('updateById', next =\u003e async rp =\u003e {\n\n  // extend resolve params with hook\n  rp.beforeRecordMutate = async (doc, resolveParams) =\u003e { ... };\n\n  return next(rp);\n});\n```\n\nor you can create wrappers for example to protect access:\n\n```ts\nfunction adminAccess(resolvers) {\n  Object.keys(resolvers).forEach((k) =\u003e {\n    resolvers[k] = resolvers[k].wrapResolve(next =\u003e async rp =\u003e {\n\n      // extend resolve params with hook\n      rp.beforeRecordMutate = async function(doc, rp) { ... }\n\n      return next(rp)\n    })\n  })\n  return resolvers\n}\n\n// and wrap the resolvers\nschemaComposer.Mutation.addFields({\n  createResource: ResourceTC.mongooseResolvers.createOne(),\n  createResources: ResourceTC.mongooseResolvers.createMany(),\n  ...adminAccess({\n    updateResource: ResourceTC.mongooseResolvers.updateById(),\n    removeResource: ResourceTC.mongooseResolvers.removeById(),\n  }),\n});\n```\n\n### How can I restrict access to certain fields or documents?\n\nThis library allows modifying the query before it is executed using the `beforeQuery` hook. This lets us prevent certain fields or documents from being read. Here's an example of restricting access to specific fields:\n\n```ts\nschemaComposer.Query.addFields({\n  userOne: UserTC.mongooseResolvers.findOne().wrapResolve((next) =\u003e (rp) =\u003e {\n    const { role } = rp.context;\n\n    rp.beforeQuery = (query: Query\u003cunknown, unknown\u003e) =\u003e {\n      if (role === 'admin') {\n        // Don't change the projection and still allow all fields to be read\n      } else if (role === 'moderator') {\n        // Only allow the name, age, and gender fields to be read\n        query.projection({ name: 1, age: 1, gender: 1 });\n      } else if (role === 'public') {\n        // Only allow the name field to be read\n        query.projection({ name: 1 });\n      }\n    };\n\n    return next(rp);\n  }),\n});\n```\n\nNote that fields that are sometimes restricted should not be marked as required in the mongoose schema. Otherwise, when you query them you will get a \"Cannot return null for non-nullable field\" error because the database query didn't return a value for the field.\n\nYou can also use `beforeQuery` to hide certain documents from the query. Here's an example:\n\n```ts\nschemaComposer.Query.addFields({\n  postMany: PostTC.mongooseResolvers.findMany().wrapResolve((next) =\u003e (rp) =\u003e {\n    const { userId } = rp.context;\n\n    rp.beforeQuery = (query: Query\u003cunknown, unknown\u003e) =\u003e {\n      // Only allow users to see their own posts\n      query.where('authorId', userId);\n    };\n\n    return next(rp);\n  }),\n});\n```\n\nBoth of these examples require putting extra data in the resolver context. Here's how to attach context data in Apollo Server:\n\n```ts\nconst server = new ApolloServer({\n  schema: schemaComposer.buildSchema(),\n  context() {\n    // This role should actually come from a JWT or something\n    return { role: 'admin' };\n  },\n});\n```\n\nOther GraphQL servers are likely similar.\n\n### How can I push/pop or add/remove values to arrays?\n\nThe default resolvers, by design, will replace (overwrite) any supplied array object when using e.g. `updateById`. If you want to push or pop a value in an array you can use a custom resolver with a native MongoDB call.\n\nFor example (push):\n\n```ts\nschemaComposer.Mutation.addFields({\n  userPushToArray: {\n    type: UserTC,\n    args: { userId: 'MongoID!', valueToPush: 'String' },\n    resolve: async (source, args, context, info) =\u003e {\n      const user = await User.update(\n        { _id: args.userId },\n        { $push: { arrayToPushTo: args.valueToPush } }\n      );\n      if (!user) return null // or gracefully return an error etc...\n      return User.findOne({ _id: args.userId }) // return the record\n    }\n  }\n})\n```\n\n`User` is the corresponding Mongoose model. If you do not wish to allow duplicates in the array then replace `$push` with `$addToSet`. Read the graphql-compose docs on custom resolvers for more info: https://graphql-compose.github.io/docs/en/basics-resolvers.html\n\nNB if you set `unique: true` on the array then using the `update` `$push` approach will not check for duplicates, this is due to a MongoDB bug: https://jira.mongodb.org/browse/SERVER-1068. For more usage examples with `$push` and arrays see the MongoDB docs here https://docs.mongodb.com/manual/reference/operator/update/push/. Also note that `$push` will preserve order in the array (append to end of array) whereas `$addToSet` will not.\n\n### Is it possible to use several schemas?\n\nBy default `composeMongoose` uses global `schemaComposer` for generated types. If you need to create different GraphQL schemas you need create own `schemaComposer`s and provide them to `customizationOptions`:\n\n```ts\nimport { SchemaComposer } from 'graphql-compose';\n\nconst schema1 = new SchemaComposer();\nconst schema2 = new SchemaComposer();\n\nconst UserTCForSchema1 = composeMongoose(User, { schemaComposer: schema1 });\nconst UserTCForSchema2 = composeMongoose(User, { schemaComposer: schema2 });\n```\n\n### Embedded documents has `_id` field and you don't need it?\n\nJust turn them off in mongoose:\n\n```ts\nconst UsersSchema = new Schema({\n  _id: { type: String }\n  emails: [{\n    _id: false, // \u003c-- disable id addition in mongoose\n    address: { type: String },\n    verified: Boolean\n  }]\n});\n```\n\n### Can field name in schema have different name in database?\n\nYes, it can. This package understands mongoose [`alias` option](https://mongoosejs.com/docs/guide.html#aliases) for fields. Just provide `alias: 'country'` for field `c` and you get `country` field name in GraphQL schema and Mongoose model but `c` field in database:\n\n```ts\nconst childSchema = new Schema({\n  c: {\n    type: String,\n    alias: 'country'\n  }\n});\n```\n\n## Backers\n\nThank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/graphql-compose#backer)]\n\n\u003ca href=\"https://opencollective.com/graphql-compose#backers\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/backers.svg?width=890\"\u003e\u003c/a\u003e\n\n## Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/graphql-compose#sponsor)]\n\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/0/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/0/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/1/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/1/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/2/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/2/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/3/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/3/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/4/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/4/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/5/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/5/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/6/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/6/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/7/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/7/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/8/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/8/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-compose/sponsor/9/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-compose/sponsor/9/avatar.svg\"\u003e\u003c/a\u003e\n\n## License\n\n[MIT](https://github.com/graphql-compose/graphql-compose-mongoose/blob/master/LICENSE.md)\n","funding_links":["https://github.com/sponsors/nodkz","https://opencollective.com/graphql-compose"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphql-compose%2Fgraphql-compose-mongoose","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgraphql-compose%2Fgraphql-compose-mongoose","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphql-compose%2Fgraphql-compose-mongoose/lists"}