在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):graphql-compose/graphql-compose-mongoose开源软件地址(OpenSource Url):https://github.com/graphql-compose/graphql-compose-mongoose开源编程语言(OpenSource Language):TypeScript 99.7%开源软件介绍(OpenSource Introduction):graphql-compose-mongooseThis is a plugin for graphql-compose, which derives GraphQLType from your mongoose model. Also derives bunch of internal GraphQL Types. Provide all CRUD resolvers, including Release Notes for v9.0.0 contains a lot of improvements. It's strongly recommended for reading before upgrading from v8.
Installationnpm install graphql graphql-compose mongoose graphql-compose-mongoose --save Modules Intro videoViktor Kjartansson created a quite solid intro for https://www.youtube.com/watch?v=RXcY-OoGnQ8 (23 mins) ExampleLive demo: https://graphql-compose.herokuapp.com/ Source code: https://github.com/graphql-compose/graphql-compose-examples Small explanation for variables naming:
import mongoose from 'mongoose';
import { composeMongoose } from 'graphql-compose-mongoose';
import { schemaComposer } from 'graphql-compose';
// STEP 1: DEFINE MONGOOSE SCHEMA AND MODEL
const LanguagesSchema = new mongoose.Schema({
language: String,
skill: {
type: String,
enum: ['basic', 'fluent', 'native'],
},
});
const UserSchema = new mongoose.Schema({
name: String, // standard types
age: {
type: Number,
index: true,
},
ln: {
type: [LanguagesSchema], // you may include other schemas (here included as array of embedded documents)
default: [],
alias: 'languages', // in schema `ln` will be named as `languages`
},
contacts: { // another mongoose way for providing embedded documents
email: String,
phones: [String], // array of strings
},
gender: { // enum field with values
type: String,
enum: ['male', 'female'],
},
someMixed: {
type: mongoose.Schema.Types.Mixed,
description: 'Can be any mixed type, that will be treated as JSON GraphQL Scalar Type',
},
});
const User = mongoose.model('User', UserSchema);
// STEP 2: CONVERT MONGOOSE MODEL TO GraphQL PIECES
const customizationOptions = {}; // left it empty for simplicity, described below
const UserTC = composeMongoose(User, customizationOptions);
// STEP 3: ADD NEEDED CRUD USER OPERATIONS TO THE GraphQL SCHEMA
// via graphql-compose it will be much much easier, with less typing
schemaComposer.Query.addFields({
userById: UserTC.mongooseResolvers.findById(),
userByIds: UserTC.mongooseResolvers.findByIds(),
userOne: UserTC.mongooseResolvers.findOne(),
userMany: UserTC.mongooseResolvers.findMany(),
userDataLoader: UserTC.mongooseResolvers.dataLoader(),
userDataLoaderMany: UserTC.mongooseResolvers.dataLoaderMany(),
userByIdLean: UserTC.mongooseResolvers.findById({ lean: true }),
userByIdsLean: UserTC.mongooseResolvers.findByIds({ lean: true }),
userOneLean: UserTC.mongooseResolvers.findOne({ lean: true }),
userManyLean: UserTC.mongooseResolvers.findMany({ lean: true }),
userDataLoaderLean: UserTC.mongooseResolvers.dataLoader({ lean: true }),
userDataLoaderManyLean: UserTC.mongooseResolvers.dataLoaderMany({ lean: true }),
userCount: UserTC.mongooseResolvers.count(),
userConnection: UserTC.mongooseResolvers.connection(),
userPagination: UserTC.mongooseResolvers.pagination(),
});
schemaComposer.Mutation.addFields({
userCreateOne: UserTC.mongooseResolvers.createOne(),
userCreateMany: UserTC.mongooseResolvers.createMany(),
userUpdateById: UserTC.mongooseResolvers.updateById(),
userUpdateOne: UserTC.mongooseResolvers.updateOne(),
userUpdateMany: UserTC.mongooseResolvers.updateMany(),
userRemoveById: UserTC.mongooseResolvers.removeById(),
userRemoveOne: UserTC.mongooseResolvers.removeOne(),
userRemoveMany: UserTC.mongooseResolvers.removeMany(),
});
// STEP 4: BUILD GraphQL SCHEMA OBJECT
const schema = schemaComposer.buildSchema();
export default schema;
// STEP 5: DEMO USE OF GraphQL SCHEMA OBJECT
// Just a demo, normally you'd pass schema object to server such as Apollo server.
import { graphql } from 'graphql';
(async () => {
await mongoose.connect('mongodb://localhost:27017/test');
await mongoose.connection.dropDatabase();
await User.create({ name: 'alice', age: 29, gender: 'female' });
await User.create({ name: 'maria', age: 31, gender: 'female' });
const bob = await User.create({ name: 'bob', age: 30, gender: 'male' });
const response1 = await graphql({
schema,
source: 'query { userMany { _id name } }',
});
console.dir(response1, { depth: 5 });
const response2 = await graphql({
schema,
source: 'query($id: MongoID!) { userById(_id: $id) { _id name } }',
variableValues: { id: bob._id },
});
console.dir(response2, { depth: 5 });
const response3 = await graphql({
schema,
source: 'mutation($id: MongoID!, $name: String) { userUpdateOne(filter: {_id: $id}, record: { name: $name }) { record { _id name } } }',
variableValues: { id: bob._id, name: 'bill' },
});
console.dir(response3, { depth: 5 });
mongoose.disconnect();
})(); That's all! You think that is to much code? I 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. Working with Mongoose Collection Level DiscriminatorsVariable Namings
import mongoose from 'mongoose';
import { schemaComposer } from 'graphql-compose';
import { composeMongooseDiscriminators } from 'graphql-compose-mongoose';
// pick a discriminatorKey
const DKey = 'type';
const enumCharacterType = {
PERSON: 'Person',
DROID: 'Droid',
};
// DEFINE BASE SCHEMA
const CharacterSchema = new mongoose.Schema({
// _id: field...
type: {
type: String,
required: true,
enum: (Object.keys(enumCharacterType): Array<string>),
description: 'Character type Droid or Person',
},
name: String,
height: Number,
mass: Number,
films: [String],
});
// DEFINE DISCRIMINATOR SCHEMAS
const DroidSchema = new mongoose.Schema({
makeDate: String,
primaryFunction: [String],
});
const PersonSchema = new mongoose.Schema({
gender: String,
hairColor: String,
starships: [String],
});
// set discriminator Key
CharacterSchema.set('discriminatorKey', DKey);
// create base Model
const CharacterModel = mongoose.model('Character', CharacterSchema);
// create mongoose discriminator models
const DroidModel = CharacterModel.discriminator(enumCharacterType.DROID, DroidSchema);
const PersonModel = CharacterModel.discriminator(enumCharacterType.PERSON, PersonSchema);
// create DiscriminatorTypeComposer
const baseOptions = { // regular TypeConverterOptions, passed to composeMongoose
fields: {
remove: ['friends'],
}
}
const CharacterDTC = composeMongooseDiscriminators(CharacterModel, baseOptions);
// create Discriminator Types
const droidTypeConverterOptions = { // this options will be merged with baseOptions -> customizationsOptions
fields: {
remove: ['makeDate'],
}
};
const DroidTC = CharacterDTC.discriminator(DroidModel, droidTypeConverterOptions);
const PersonTC = CharacterDTC.discriminator(PersonModel); // baseOptions -> customizationsOptions applied
// You may now use CharacterDTC to add fields to all Discriminators
// Use DroidTC, `PersonTC as any other ObjectTypeComposer.
schemaComposer.Mutation.addFields({
droidCreate: DroidTC.getResolver('createOne'),
personCreate: PersonTC.getResolver('createOne'),
});
const schema = schemaComposer.buildSchema();
describe('createOne', () => {
it('should create child document without specifying DKey', async () => {
const res = await graphql.graphql({
schema,
source: `mutation CreateCharacters {
droidCreate(record: {name: "Queue XL", modelNumber: 360 }) {
record {
__typename
type
name
modelNumber
}
}
personCreate(record: {name: "mernxl", dob: 57275272}) {
record {
__typename
type
name
dob
}
}
}`
);
expect(res).toEqual({
data: {
droidCreate: {
record: { __typename: 'Droid', type: 'Droid', name: 'Queue XL', modelNumber: 360 },
},
personCreate: {
record: { __typename: 'Person', type: 'Person', name: 'mernxl', dob: 57275272 },
},
},
});
});
}); Customization options
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论