@@ -92,9 +92,9 @@ const User = mongoose.model('User', UserSchema);
9292const customizationOptions = {}; // left it empty for simplicity, described below
9393const UserTC = composeWithMongoose (User, customizationOptions);
9494
95- // STEP 3: CREATE CRAZY GraphQL SCHEMA WITH ALL CRUD USER OPERATIONS
95+ // STEP 3: Add needed CRUD User operations to the GraphQL Schema
9696// via graphql-compose it will be much much easier, with less typing
97- schemaComposer .rootQuery () .addFields ({
97+ schemaComposer .Query .addFields ({
9898 userById: UserTC .getResolver (' findById' ),
9999 userByIds: UserTC .getResolver (' findByIds' ),
100100 userOne: UserTC .getResolver (' findOne' ),
@@ -104,7 +104,7 @@ schemaComposer.rootQuery().addFields({
104104 userPagination: UserTC .getResolver (' pagination' ),
105105});
106106
107- schemaComposer .rootMutation () .addFields ({
107+ schemaComposer .Mutation .addFields ({
108108 userCreate: UserTC .getResolver (' createOne' ),
109109 userUpdateById: UserTC .getResolver (' updateById' ),
110110 userUpdateOne: UserTC .getResolver (' updateOne' ),
@@ -122,6 +122,126 @@ You think that is to much code?
122122I 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.
123123
124124
125+ ### Working with Mongoose Collection Level Discriminators
126+ Variable Namings
127+ * ` ...DTC ` - Suffix for a ` DiscriminatorTypeComposer ` instance, which is also an instance of ` TypeComposer ` . All fields and Relations manipulations on this instance affects all registered discriminators and the Discriminator Interface.
128+
129+ ``` js
130+ import mongoose from ' mongoose' ;
131+ import { schemaComposer } from ' graphql-compose' ;
132+ import { composeWithMongooseDiscriminators } from ' graphql-compose-mongoose' ;
133+
134+ // pick a discriminatorKey
135+ const DKey = ' type' ;
136+
137+ const enumCharacterType = {
138+ PERSON : ' Person' ,
139+ DROID : ' Droid' ,
140+ };
141+
142+ // DEFINE BASE SCHEMA
143+ const CharacterSchema = new mongoose.Schema ({
144+ // _id: field...
145+ type: {
146+ type: String ,
147+ require: true ,
148+ enum: (Object .keys (enumCharacterType): Array < string> ),
149+ description: ' Character type Droid or Person' ,
150+ },
151+
152+ name: String ,
153+ height: Number ,
154+ mass: Number ,
155+ films: [String ],
156+ });
157+
158+ // DEFINE DISCRIMINATOR SCHEMAS
159+ const DroidSchema = new mongoose.Schema ({
160+ makeDate: String ,
161+ primaryFunction: [String ],
162+ });
163+
164+ const PersonSchema = new mongoose.Schema ({
165+ gender: String ,
166+ hairColor: String ,
167+ starships: [String ],
168+ });
169+
170+ // set discriminator Key
171+ CharacterSchema .set (' discriminatorKey' , DKey);
172+
173+ // create base Model
174+ const CharacterModel = mongoose .model (' Character' , CharacterSchema);
175+
176+ // create mongoose discriminator models
177+ const DroidModel = CharacterModel .discriminator (enumCharacterType .DROID , DroidSchema);
178+ const PersonModel = CharacterModel .discriminator (enumCharacterType .PERSON , PersonSchema);
179+
180+ // create DiscriminatorTypeComposer
181+ const baseOptions = { // regular TypeConverterOptions, passed to composeWithMongoose
182+ fields: {
183+ remove: [' friends' ],
184+ }
185+ }
186+ const CharacterDTC = composeWithMongooseDiscriminators (CharacterModel, baseOptions);
187+
188+ // create Discriminator Types
189+ const droidTypeConverterOptions = { // this options will be merged with baseOptions -> customisationsOptions
190+ fields: {
191+ remove: [' makeDate' ],
192+ }
193+ };
194+ const DroidTC = CharacterDTC .discriminator (DroidModel, droidTypeConverterOptions);
195+ const PersonTC = CharacterDTC .discriminator (PersonModel); // baseOptions -> customisationsOptions applied
196+
197+ // You may now use CharacterDTC to add fields to all Discriminators
198+ // Use DroidTC, `PersonTC as any other TypeComposer.
199+ schemaComposer .Mutation .addFields ({
200+ droidCreate: DroidTC .getResolver (' createOne' ),
201+ personCreate: PersonTC .getResolver (' createOne' ),
202+ });
203+
204+ const schema = schemaComposer .buildSchema ();
205+
206+ describe (' createOne' , () => {
207+ it (' should create child document without specifying DKey' , async () => {
208+ const res = await graphql .graphql (
209+ schema,
210+ ` mutation CreateCharacters {
211+ droidCreate(record: {name: "Queue XL", modelNumber: 360 }) {
212+ record {
213+ __typename
214+ type
215+ name
216+ modelNumber
217+ }
218+ }
219+
220+ personCreate(record: {name: "mernxl", dob: 57275272}) {
221+ record {
222+ __typename
223+ type
224+ name
225+ dob
226+ }
227+ }
228+ }`
229+ );
230+
231+ expect (res).toEqual ({
232+ data: {
233+ droidCreate: {
234+ record: { __typename: ' Droid' , type: ' Droid' , name: ' Queue XL' , modelNumber: 360 },
235+ },
236+ personCreate: {
237+ record: { __typename: ' Person' , type: ' Person' , name: ' mernxl' , dob: 57275272 },
238+ },
239+ },
240+ });
241+ });
242+ });
243+ ```
244+
125245## FAQ
126246
127247### Can I get generated vanilla GraphQL types?
@@ -273,7 +393,7 @@ The typical implementation may be like this:
273393// extend resolve params with hook
274394rp .beforeRecordMutate = async function (doc , rp ) {
275395 doc .userTouchedAt = new Date ();
276-
396+
277397 const canMakeUpdate = await performAsyncTask ( ... provide data from doc... )
278398 if (! canMakeUpdate) {
279399 throw new Error (' Forbidden!' );
@@ -304,7 +424,7 @@ function adminAccess(resolvers) {
304424
305425 // extend resolve params with hook
306426 rp .beforeRecordMutate = async function (doc , rp ) { ... }
307-
427+
308428 return next (rp)
309429 })
310430 })
@@ -465,4 +585,3 @@ This plugin adds `pagination` resolver.
465585
466586## License
467587[ MIT] ( https://github.com/graphql-compose/graphql-compose-mongoose/blob/master/LICENSE.md )
468-
0 commit comments