• Stars
    star
    189
  • Rank 204,649 (Top 5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 11 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Easily create a Mongoose Service for Feathersjs.

feathers-mongoose

CI Dependency Status Download Status

A Feathers database adapter for Mongoose, an object modeling tool for MongoDB.

$ npm install --save mongoose feathers-mongoose

Important: feathers-mongoose implements the Feathers Common database adapter API and querying syntax.

This adapter also requires a running MongoDB database server.

API

service(options)

Returns a new service instance initialized with the given options. Model has to be a Mongoose model. See the Mongoose Guide for more information on defining your model.

const mongoose = require('mongoose');
const service = require('feathers-mongoose');

// A module that exports your Mongoose model
const Model = require('./models/message');

// Make Mongoose use the ES6 promise
mongoose.Promise = global.Promise;

// Connect to a local database called `feathers`
mongoose.connect('mongodb://localhost:27017/feathers');

app.use('/messages', service({ Model }));
app.use('/messages', service({ Model, lean, id, events, paginate }));

Options:

  • Model (required) - The Mongoose model definition
  • lean (optional, default: true) - Runs queries faster by returning plain objects instead of Mongoose models.
  • id (optional, default: '_id') - The name of the id field property.
  • events (optional) - A list of custom service events sent by this service
  • paginate (optional) - A pagination object containing a default and max page size
  • whitelist (optional) - A list of additional query parameters to allow (e..g [ '$regex', '$populate' ])
  • multi (optional) - Allow create with arrays and update and remove with id null to change multiple items. Can be true for all methods or an array of allowed methods (e.g. [ 'remove', 'create' ])
  • overwrite (optional, default: true) - Overwrite the document when update, making mongoose detect is new document and trigger default value for unspecified properties in mongoose schema.
  • discriminators (optional) - A list of mongoose models that inherit from Model.
  • useEstimatedDocumentCount (optional, default: false) - Use estimatedDocumentCount instead (usually not necessary)
  • queryModifier (optional) - A function that takes in the raw mongoose Query object and params, which modifies all find and get requests unless overridden. (see Query Modifiers below)
  • queryModifierKey (optional, default: 'queryModifier') - The key to use to get the override query modifier function from the params. (see Query Modifiers below)

Important: To avoid odd error handling behaviour, always set mongoose.Promise = global.Promise. If not available already, Feathers comes with a polyfill for native Promises.

Important: When setting lean to false, Mongoose models will be returned which can not be modified unless they are converted to a regular JavaScript object via toObject.

Note: You can get access to the Mongoose model via this.Model inside a hook and use it as usual. See the Mongoose Guide for more information on defining your model.

params.mongoose

When making a service method call, params can contain a mongoose property which allows you to modify the options used to run the Mongoose query. Normally, this will be set in a before hook:

app.service('messages').hooks({
  before: {
    patch(context) {
      // Set some additional Mongoose options
      // The adapter tries to use these settings by defaults
      // but they can always be changed here
      context.params.mongoose = {
        runValidators: true,
        setDefaultsOnInsert: true
      }
    }
  }
});

The mongoose property is also useful for performing upserts on a patch request. "Upserts" do an update if a matching record is found, or insert a record if there's no existing match. The following example will create a document that matches the data, or if there's already a record that matches the params.query, that record will be updated.

Using the writeResult mongoose option will return the write result of a patch operation, including the _ids of all upserted or modified documents. This can be helpful alongside the upsert flag, for detecting whether the outcome was a find or insert operation. More on write results is available in the Mongo documentation

const data = { address: '123', identifier: 'my-identifier' }
const params = {
  query: { address: '123' },
  mongoose: { upsert: true, writeResult: true }
}
app.service('address-meta').patch(null, data, params)

Example

Here's a complete example of a Feathers server with a messages Mongoose service.

$ npm install @feathersjs/feathers @feathersjs/errors @feathersjs/express @feathersjs/socketio mongoose feathers-mongoose

In message-model.js:

const mongoose = require('mongoose');

const Schema = mongoose.Schema;
const MessageSchema = new Schema({
  text: {
    type: String,
    required: true
  }
});
const Model = mongoose.model('Message', MessageSchema);

module.exports = Model;

Then in app.js:

const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');

const mongoose = require('mongoose');
const service = require('feathers-mongoose');

const Model = require('./message-model');

mongoose.Promise = global.Promise;

// Connect to your MongoDB instance(s)
mongoose.connect('mongodb://localhost:27017/feathers');

// Create an Express compatible Feathers application instance.
const app = express(feathers());

// Turn on JSON parser for REST services
app.use(express.json());
// Turn on URL-encoded parser for REST services
app.use(express.urlencoded({extended: true}));
// Enable REST services
app.configure(express.rest());
// Enable Socket.io services
app.configure(socketio());
// Connect to the db, create and register a Feathers service.
app.use('/messages', service({
  Model,
  lean: true, // set to false if you want Mongoose documents returned
  paginate: {
    default: 2,
    max: 4
  }
}));
app.use(express.errorHandler());

// Create a dummy Message
app.service('messages').create({
  text: 'Message created on server'
}).then(function(message) {
  console.log('Created message', message);
});

// Start the server.
const port = 3030;
app.listen(port, () => {
    console.log(`Feathers server listening on port ${port}`);
});

You can run this example by using node app and go to localhost:3030/messages.

Querying, Validation

Mongoose by default gives you the ability to add validations at the model level. Using an error handler like the one that comes with Feathers your validation errors will be formatted nicely right out of the box!

For more information on querying and validation refer to the Mongoose documentation.

$populate

For Mongoose, the special $populate query parameter can be used to allow Mongoose query population.

Important: $populate has to be whitelisted explicitly since it can expose protected fields in sub-documents (like the user password) which have to be removed manually.

const mongoose = require('feathers-mongoose');

app.use('/posts', mongoose({
  Model,
  whitelist: [ '$populate' ]
});

app.service('posts').find({
  query: { $populate: 'user' }
});

Error handling

As of v7.3.0, the original Mongoose error can be retrieved on the server via:

const { ERROR } = require('feathers-mongoose');

try {
  await app.service('posts').create({ value: 'invalid' });
} catch(error) {
  // error is a FeathersError
  // Safely retrieve the original Mongoose error
  const mongooseError = error[ERROR];
}

Discriminators (Inheritance)

Instead of strict inheritance, Mongoose uses discriminators as their schema inheritance model. To use them, pass in a discriminatorKey option to your schema object and use Model.discriminator('modelName', schema) instead of mongoose.model()

Feathers comes with full support for mongoose discriminators, allowing for automatic fetching of inherited types. A typical use case might look like:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Post = require('./post');
var feathers = require('@feathersjs/feathers');
var app = feathers();
var service = require('feathers-mongoose');

// Discriminator key, we'll use this later to refer to all text posts
var options = {
  discriminatorKey: '_type'
};

var TextPostSchema = new Schema({
  text: { type: String, default: null }
}, options);

// Note the use of `Post.discriminator` rather than `mongoose.discriminator`.
var TextPost = Post.discriminator('text', TextPostSchema);

// Using the discriminators option, let feathers know about any inherited models you may have
// for that service
app.use('/posts', service({
  Model: Post,
  discriminators: [TextPost]
}))

Without support for discriminators, when you perform a .get on the posts service, you'd only get back Post models, not TextPost models. Now in your query, you can specify a value for your discriminatorKey:

{
  _type: 'text'
}

and Feathers will automatically swap in the correct model and execute the query it instead of its parent model.

Collation Support

This adapter includes support for collation and case insensitive indexes available in MongoDB v3.4. Collation parameters may be passed using the special collation parameter to the find(), remove() and patch() methods.

Example: Patch records with case-insensitive alphabetical ordering

The example below would patch all student records with grades of 'c' or 'C' and above (a natural language ordering). Without collations this would not be as simple, since the comparison { $gt: 'c' } would not include uppercase grades of 'C' because the code point of 'C' is less than that of 'c'.

const patch = { shouldStudyMore: true };
const query = { grade: { $gte: 'c' } };
const collation = { locale: 'en', strength: 1 };
students.patch(null, patch, { query, collation }).then( ... );

Example: Find records with a case-insensitive search

Similar to the above example, this would find students with a grade of 'c' or greater, in a case-insensitive manner.

const query = { grade: { $gte: 'c' } };
const collation = { locale: 'en', strength: 1 };
students.find({ query, collation }).then( ... );

For more information on MongoDB's collation feature, visit the collation reference page.

Mongo-DB Transaction

This adapter includes support to enable database transaction to rollback the persisted records for any error occured for a api call. This requires Mongo-DB v4.x installed and replica-set enabled.

Start working with transaction enabled by adding the following lines in app.hooks.js or <any-service>.hooks.js.

const TransactionManager = require('feathers-mongoose').TransactionManager;
const isTransactionEnable = process.env.TRANSACTION_ENABLE || false;
const skipPath = ['login'];

let moduleExports = {
  before: {
    all: [],
    find: [],
    get: [],
    create: [
      when(isTransactionEnable, async hook =>
        TransactionManager.beginTransaction(hook, skipPath)
      )
    ],
    update: [
      when(isTransactionEnable, async hook =>
        TransactionManager.beginTransaction(hook, skipPath)
      )
    ],
    patch: [],
    remove: []
  },

  after: {
    all: [],
    find: [],
    get: [],
    create: [when(isTransactionEnable, TransactionManager.commitTransaction)],
    update: [when(isTransactionEnable, TransactionManager.commitTransaction)],
    patch: [],
    remove: []
  },

  error: {
    all: [],
    find: [],
    get: [],
    create: [when(isTransactionEnable, TransactionManager.rollbackTransaction)],
    update: [when(isTransactionEnable, TransactionManager.rollbackTransaction)],
    patch: [],
    remove: []
  }
};

module.exports = moduleExports;

Query Modifiers

Sometimes it's important to use an unusual Mongoose Query method, like specifying whether to read from a primary or secondary node, but maybe only for certain requests.

You can access the internal Mongoose Query object used for a find/get request by specifying the queryModifier function. It is also possible to override that global function by specifying the function in a requests params.

// Specify a global query modifier when creating the service
app.use('/messages', service({
  Model,
  queryModifier: (query, params) => {
    query.read('secondaryPreferred');
  }
}));

app.service('messages').find({
  query: { ... },
}).then((result) => {
  console.log('Result from secondary:', result)
});

// Override the modifier on a per-request basis
app.service('messages').find({
  query: { ... },
  queryModifier: (query, params) => {
    query.read('primaryPreferred');
  }
}).then((result) => {
  console.log('Result from primary:', result)
});

// Disable the global modifier on a per-request basis
app.service('messages').find({
  query: { ... },
  queryModifier: false
}).then((result) => {
  console.log('Result from default option:', result)
});

Note: Due to replication lag, a secondary node can have "stale" data. You should ensure that this "staleness" will not be an issue for your application before reading from the secondary set.

Contributing

This module is community maintained and open for pull requests. Features and bug fixes should contain

  • The bug fix / feature code
  • Tests to reproduce the bug or test the feature
  • Documentation updates (if necessary)

To contribute, fork and clone the repository. To run the tests, a MongoDB v4.0.0 server is required. If you do not have a MongoDB server running you can start one with:

npm run mongodb

The command needs to stay open while running the tests with

npm test

License

MIT

Authors

More Repositories

1

feathers-vuex

Integration of FeathersJS, Vue, and Nuxt for the artisan developer
TypeScript
445
star
2

authentication

[MOVED] Feathers local, token, and OAuth authentication over REST and Websockets using JSON Web Tokens (JWT) with PassportJS.
JavaScript
317
star
3

feathers-authentication-management

Adds sign up verification, forgotten password reset, and other capabilities to local feathers-authentication
TypeScript
247
star
4

feathers-swagger

Add documentation to your FeatherJS services and feed them to Swagger UI.
JavaScript
225
star
5

feathers-sync

Synchronize service events between Feathers application instances
JavaScript
222
star
6

feathers-reactive

Reactive API extensions for Feathers services
TypeScript
216
star
7

feathers-sequelize

A Feathers service adapter for the Sequelize ORM. Supporting MySQL, MariaDB, Postgres, SQLite, and SQL Server
TypeScript
208
star
8

feathers-react-native-chat

A React Native example chat app using feathers
JavaScript
196
star
9

feathers-hooks-common

Useful hooks for use with FeathersJS services.
TypeScript
193
star
10

feathers-permissions

Simple role and service method permissions for Feathers
JavaScript
184
star
11

cli

The command line interface for scaffolding Feathers applications
JavaScript
155
star
12

feathers-mongodb

A mongodb service for feathers
JavaScript
122
star
13

generator-feathers

A Yeoman generator for a Feathers application
JavaScript
120
star
14

feathers-authentication-hooks

Useful hooks for authentication and authorization
JavaScript
115
star
15

feathers-redux

Integrate Feathers with your Redux store
JavaScript
114
star
16

feathers-knex

Service adapters for KnexJS a query builder for PostgreSQL, MySQL, MariaDB, Oracle and SQLite3
JavaScript
112
star
17

client

[MOVED] Client side Feathers build
JavaScript
111
star
18

feathers-chat-vuex-0.7

Feathers Chat application build using feathers-vuex
CSS
102
star
19

feathers-objection

Feathers database adapter for Objection.js, an ORM based on KnexJS SQL query builder for Postgres, Redshift, MSSQL, MySQL, MariaDB, SQLite3, and Oracle. Forked from feathers-knex.
JavaScript
98
star
20

feathers-chat-react

Feathers Chat application build using React and create-react-app
JavaScript
97
star
21

feathers-batch

Batch multiple Feathers service calls into one
JavaScript
96
star
22

feathers-stripe

TypeScript
95
star
23

feathers-blob

Feathers service for blob storage, like S3.
JavaScript
92
star
24

feathers-rethinkdb

A Feathers service adapter for RethinkDB.
JavaScript
85
star
25

feathers-nedb

A service using NeDB, an embedded datastore for Node.js
TypeScript
83
star
26

feathers-mailer

Feathers mailer service using nodemailer
TypeScript
83
star
27

feathers-elasticsearch

Feathersjs adapter for Elasticsearch
JavaScript
78
star
28

validate-joi

Feathers hook utility for schema validation, sanitization and client notification using Joi.
JavaScript
67
star
29

feathers-hooks

Service method hooks for easy authorization and processing
JavaScript
59
star
30

feathers-chat-ts

A Feathers real-time chat application in TypeScript
TypeScript
54
star
31

feathers-rest

The Feathers HTTP(S) transport plugin for REST APIs
JavaScript
52
star
32

feathers-chat-angular

An angular implementation of a feathers-chat client
TypeScript
52
star
33

feathers-chat-vuex

Feathers Chat built with Feathers-Vuex 3.0
CSS
50
star
34

feathers-swift

FeathersJS Swift SDK, written with love.
Swift
50
star
35

feathers-memory

An in memory feathers service
JavaScript
44
star
36

authentication-client

[MOVED] The authentication client
JavaScript
41
star
37

feathers-localstorage

A client side service based on feathers-memory that persists to LocalStorage
JavaScript
38
star
38

socketio

[MOVED] The Feathers Socket.io websocket transport plugin
JavaScript
37
star
39

schema

JavaScript and TypeScript schema definitions
TypeScript
35
star
40

errors

[MOVED] Feathers errors for server and client
JavaScript
35
star
41

authentication-jwt

[MOVED] JWT authentication strategy for feathers-authentication using Passport
JavaScript
30
star
42

configuration

[MOVED] A plugin for configuring a Feathers application
JavaScript
28
star
43

feathers-profiler

Log feathers service calls and gather profile information on them.
JavaScript
27
star
44

feathers-bootstrap

Feathers application bootstrap and configuration using JSON files
JavaScript
26
star
45

authentication-oauth2

[MOVED] OAuth 2 plugin for feathers-authentication
JavaScript
26
star
46

feathers-mailgun

A Feathers service for Mailgun
JavaScript
26
star
47

authentication-local

[MOVED] Local authentication plugin for feathers-authentication
JavaScript
26
star
48

feathers-logger

A little wrapper for convenient logging in feathers
JavaScript
23
star
49

feathers-debugger

Feathers Debugger Chrome extension
JavaScript
23
star
50

generator-feathers-plugin

A Yeoman generator for creating a FeathersJS plugin.
JavaScript
22
star
51

feathers-waterline

A Feathers adapter for the Waterline ORM
JavaScript
21
star
52

feathers-service-tests

A test harness for Feathers service implementations
JavaScript
20
star
53

feathers-authentication-ldap

LDAP authentication strategy for feathers-authentication using Passport
JavaScript
19
star
54

primus

[MOVED] The Feathers Primus websocket transport plugin
JavaScript
18
star
55

feathers-levelup

LevelUP instances as Feathers services
JavaScript
14
star
56

feathers-authentication-popups

Server and client utils for implementing popup-based authentication flows
JavaScript
14
star
57

batch-loader

Reduce requests to backend services by batching calls and caching records.
JavaScript
13
star
58

express

[MOVED] Feathers Express framework bindings and REST transport plugin
JavaScript
13
star
59

feathers-query-filters

Adds support for special query string params used for filtering data
JavaScript
12
star
60

commons

[MOVED] Shared utility functions
JavaScript
11
star
61

transport-commons

[MOVED] Shared functionality for Feathers transports
JavaScript
11
star
62

feathers-mongodb-management

Manage MongoDB Databases, Users & Collections with this Feathers service adapter
JavaScript
11
star
63

feathers-generator

A metalsmith based generator for scaffolding Feathers apps.
JavaScript
10
star
64

feathers-debugger-service

Feathers Debugger service, use with Feathers Debugger.
JavaScript
9
star
65

feathers-cassandra

Feathers service adapter for Cassandra DB based on Express-Cassandra ORM and CassanKnex query builder
JavaScript
8
star
66

rest-client

[MOVED] REST client services for different Ajax libraries
JavaScript
8
star
67

feathers-android

Android client for feathers services
Java
7
star
68

feathers-swift-socketio

FeathersSwift SocketIO Transport Provider
Swift
7
star
69

feathers-twilio

A Feathers service for talking to the Twilio API
JavaScript
7
star
70

website

The old Feathers website
Less
6
star
71

dataloader

JavaScript
6
star
72

feathers-authentication-custom

Custom authentication strategy for feathers-authentication using Passport
JavaScript
5
star
73

authentication-oauth1

[MOVED] A Feathers OAuth1.x authentication strategy
JavaScript
5
star
74

socketio-client

[MOVED] Client services for Socket.io and feathers-socketio
JavaScript
5
star
75

primus-client

[MOVED] Client services for Primus and feathers-primus
JavaScript
5
star
76

feathers-redis

A Feathers redis service adapter
JavaScript
4
star
77

tools

Codemods and other generator and repository management tools
JavaScript
3
star
78

feathers-couchbase

A Couchbase Service for feathers
JavaScript
3
star
79

feathers-swift-rest

REST Transport provider for FeathersSwift
Swift
2
star
80

feathers-ios

Feathers service client for iOS
Swift
2
star
81

feathers-sendgrid

Sendgrid service for Feathers
JavaScript
1
star