apollo-model-mongodb
v0.4.5
Published
![](cover/cover.jpg)
Downloads
41
Maintainers
Readme
apollo-model-mongodb BETA
Description
This package allows you to automatically generate Apollo Server schema and resolvers for MongoDB using Prisma-like SDL.
We like Prisma but we want to build a more flexible and customizable solution.
Quick preview on codesandbox
Note! The database connected with read-only permissions. So mutation will not work. You can create and connect your own database (for example use Atlas)
Installation
With yarn:
yarn add apollo-model-mongodb
or using npm:
npm install --save apollo-model-mongodb
Usage
Project initialization is the same as for Apollo Server. The only difference is that we use makeExecutableSchema
from this package to generate schema.
import ApolloModelMongo, { QueryExecutor } from 'apollo-model-mongodb';
const schema = await new ApolloModelMongo({
queryExecutor: QueryExecutor(db),
}).makeExecutablSchema({
typeDefs,
});
const server = new ApolloServer({
schema,
});
You can find full examples here
SDL example
type Category @model {
id: ObjectID! @id @unique @db(name: "_id")
title: String @default(value: "New Category")
parentCategory: Category @relation(storeField: "parentCategoryId")
subcategories: [Category!] @extRelation(storeField: "parentCategoryId")
posts: [Post!] @extRelation
createdAt: Date @createdAt
updatedAt: Date @updatedAt
}
type Comment {
body: String
user: User! @relation
}
type Post @model {
id: ObjectID! @id @unique @db(name: "_id")
title: String!
body: String!
category: Category @relation
keywords: [String!]
owner: User! @relation
place: GeoJSONPoint
comments: [Comment!]
}
interface User @inherit @model {
id: ObjectID! @id @unique @db(name: "_id")
username: String! @unique
}
enum AdminRole {
superadmin
moderator
}
type Admin implements User {
role: AdminRole
}
enum SubscriberRole {
free
standard
premium
}
type SubscriberProfile {
firstName: String!
lastName: String!
}
type Subscriber implements User {
role: SubscriberRole
profile: SubscriberProfile!
}
The above SDL generates this endpoint https://apollo-model-mongodb-example.now.sh
Example queries below
Directives
The model
directive
- Connects object with MongoDB collection.
- Valid locations: OBJECT or INTERFACE
- Optional
- Arguments
- collection:String
- The name of MongoDB collection * Optional (Default value is pluralized name of the object)
The unique
directive
- Add field to WHERE_UNIQUE input type
- Valid locations: FIELD
- Optional
The id
directive
- Mark field as identifier. Skip creation.
- Valid locations: FIELD
- Optional
The db
directive
- Map GraphQL field to collection.
- Valid locations: FIELD
- Optional
- Arguments
- name:String
- The name of field in collection * Required
The default
directive
- Sets a default value for a field.
- Valid locations: FIELD
- Optional
- Arguments
- value:String
- The default value for the field * Required
The inherit
directive
- Clones interface fields to objects.
- Valid locations: INTERFACE
- Required
The discriminator
directive
- Used to define field and values to resolve implementation type.
- Valid locations: INTERFACE or OBJECT
- Optional
- Arguments
- value:String
- Required
The relation
directive
- Used to define relation between two collections.
- Valid locations: FIELD
- Optional
- Arguments
- field:String
- Optional
- Default value: _id
- storeField:String
- Optional
- Default value:
${TypeName}Id${s}
The extRelation
directive
Used to define external relation between two collections (identifiers stored in related documents).
Valid locations: FIELD
Optional
Arguments
field:String
- Optional
- Default value: _id
storeField:String
- Optional
- Default value:
${TypeName}Id${s}
many:Boolean
- Optional
- Default value: false
The createdAt
directive
- Sets date on field on CREATE.
- Valid locations: FIELD
- Optional
The updatedAt
directive
- Sets date on field on CREATE and UPDATE.
- Valid locations: FIELD
Serverless
You can use this package with serverless environments. Read more here. Also take a look at example-now if you are using Zeit Now.
Customization
- You can define your own scalars and directives as for usual Apollo server.
- You can add custom modules at MongoModel stage (docs coming soon)
- All queries to DB executes with QueryExecutor function. This package has predefined one, but you can override it and add hooks or check user authorization.
const QueryExecutor = ({ type, collection, doc, docs, selector, options })=>Promise
Contribution
You are welcome to open Issues, Feature Requests and PR with new features and bug fixes
Roadmap
- Filter by Nth array element
- Add subscriptions
- Release stable version 1.0.0
- Add Moment scalar
- Improve Geo queries support
Features
- Simple query
- Simple create
- Filter
- Difficult filter
- Relation query
- Relation filter
- Relation create
- Nested create
- Interfaces
- Geo queries
Simple query
query
{
categories {
id
title
}
}
response
{
"data": {
"categories": [
{
"id": "5c3f4d84e98bd4e76e1d34d1",
"title": "root"
},
{
"id": "5c3f4dd3e98bd4e76e1d34d2",
"title": "JS"
},
{
"id": "5c3f4f46e98bd4e76e1d34d3",
"title": "MongoDB"
}
]
}
}
Simple create
query
mutation {
createCategory(data: { title: "root" }) {
id
}
}
response
{
"data": {
"createCategory": {
"id": "5c3f4d84e98bd4e76e1d34d1"
}
}
}
Filter
request
{
categories(where: { title: "root" }) {
id
title
}
}
response
{
"data": {
"categories": [
{
"id": "5c3f4d84e98bd4e76e1d34d1",
"title": "root"
}
]
}
}
Difficult filter
request
{
categories(where: { OR: [{ title: "root" }, { title: "JS" }] }) {
id
title
}
}
response
{
"data": {
"categories": [
{
"id": "5c3f4d84e98bd4e76e1d34d1",
"title": "root"
},
{
"id": "5c3f4dd3e98bd4e76e1d34d2",
"title": "JS"
}
]
}
}
Relation query
query
{
categories {
id
title
parentCategory {
title
}
}
}
response
{
"data": {
"categories": [
{
"id": "5c3f4d84e98bd4e76e1d34d1",
"title": "root",
"parentCategory": null
},
{
"id": "5c3f4dd3e98bd4e76e1d34d2",
"title": "JS",
"parentCategory": {
"title": "root"
}
},
{
"id": "5c3f4f46e98bd4e76e1d34d3",
"title": "MongoDB",
"parentCategory": {
"title": "root"
}
}
]
}
}
Relation filter
query
{
categories(where: { parentCategory: { title: "root" } }) {
id
title
}
}
response
{
"data": {
"categories": [
{
"id": "5c3f4dd3e98bd4e76e1d34d2",
"title": "JS"
},
{
"id": "5c3f4f46e98bd4e76e1d34d3",
"title": "MongoDB"
}
]
}
}
Relation create
query
mutation {
createCategory(
data: {
title: "Mongodb"
parentCategory: { connect: { id: "5c3f4d84e98bd4e76e1d34d1" } }
}
) {
id
}
}
response
{
"data": {
"createCategory": {
"id": "5c3f4f46e98bd4e76e1d34d3"
}
}
}
Nested create
query
mutation {
createSubscriber(
data: {
username: "subscriber1"
profile: { create: { firstName: "Gwion", lastName: "Britt" } }
}
) {
id
username
}
}
response
{
"data": {
"createSubscriber": {
"id": "5c3f555b190d25e7bda1dea2",
"username": "subscriber1"
}
}
}
Interfaces
Connect
query
mutation {
createPost(
data: {
title: "Build GraphQL API with Apollo"
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
owner: { connect: { Admin: { username: "admin" } } }
}
) {
id
}
}
response
{
"data": {
"createPost": {
"id": "5c401347de7e67e9540abad2"
}
}
}
Query
query
{
posts {
title
owner {
username
... on Subscriber {
profile {
firstName
lastName
}
}
}
}
}
response
{
"data": {
"posts": [
{
"title": "Build GraphQL API with Apollo",
"owner": {
"username": "admin"
}
}
]
}
}
Geo queries
query
{
posts(
where: {
place_near: {
geometry: { type: Point, coordinates: [0, 51.01] }
maxDistance: 10000
}
}
) {
id
title
place {
distance(toPoint: { type: Point, coordinates: [0, 51.01] })
}
}
}
response
{
"data": {
"posts": [
{
"id": "5c401347de7e67e9540abad2",
"title": "Build GraphQL API with Apollo",
"place": {
"distance": 1111.9492664453662
}
}
]
}
}