Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/feathersjs-ecosystem/feathers-mongodb

A mongodb service for feathers
https://github.com/feathersjs-ecosystem/feathers-mongodb

Last synced: 4 months ago
JSON representation

A mongodb service for feathers

Lists

README

        

> __Important:__ This module has been moved to `@feathersjs/mongodb` and is developed in [feathersjs/feathers](https://github.com/feathersjs/feathers)

# feathers-mongodb

[![CI](https://github.com/feathersjs-ecosystem/feathers-mongodb/workflows/CI/badge.svg)](https://github.com/feathersjs-ecosystem/feathers-mongodb/actions?query=workflow%3ACI)
[![Dependency Status](https://img.shields.io/david/feathersjs-ecosystem/feathers-mongodb.svg?style=flat-square)](https://david-dm.org/feathersjs-ecosystem/feathers-mongodb)
[![Download Status](https://img.shields.io/npm/dm/feathers-mongodb.svg?style=flat-square)](https://www.npmjs.com/package/feathers-mongodb)

A [Feathers](https://feathersjs.com) database adapter for [MongoDB](https://www.mongodb.org/) using [official NodeJS driver for MongoDB](https://www.npmjs.com/package/mongodb).

```bash
$ npm install --save mongodb feathers-mongodb
```

> __Important:__ `feathers-mongodb` implements the [Feathers Common database adapter API](https://docs.feathersjs.com/api/databases/common.html) and [querying syntax](https://docs.feathersjs.com/api/databases/querying.html).

> This adapter also requires a [running MongoDB](https://docs.mongodb.com/getting-started/shell/#) database server.

## API

### `service(options)`

Returns a new service instance initialized with the given options. `Model` has to be a MongoDB collection.

```js
const MongoClient = require('mongodb').MongoClient;
const service = require('feathers-mongodb');

MongoClient.connect('mongodb://localhost:27017/feathers').then(client => {
app.use('/messages', service({
Model: client.db('feathers').collection('messages')
}));
app.use('/messages', service({ Model, id, events, paginate }));
});
```

__Options:__

- `Model` (**required**) - The MongoDB collection instance
- `id` (*optional*, default: `'_id'`) - The name of the id field property. By design, MongoDB will always add an `_id` property.
- `disableObjectify` (*optional*, default `false`) - This will disable the objectify of the id field if you want to use normal strings
- `events` (*optional*) - A list of [custom service events](https://docs.feathersjs.com/api/events.html#custom-events) sent by this service
- `paginate` (*optional*) - A [pagination object](https://docs.feathersjs.com/api/databases/common.html#pagination) containing a `default` and `max` page size
- `whitelist` (*optional*) - A list of additional query parameters to allow (e..g `[ '$regex', '$geoNear' ]`)
- `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' ]`)
- `useEstimatedDocumentCount` (*optional*, default `false`) - If `true` document counting will rely on `estimatedDocumentCount` instead of `countDocuments`

### params.mongodb

When making a [service method](https://docs.feathersjs.com/api/services.html) call, `params` can contain an `mongodb` property (for example, `{upsert: true}`) which allows to modify the options used to run the MongoDB query.

#### Transactions

You can utilized a [MongoDB Transactions](https://docs.mongodb.com/manual/core/transactions/) by passing a `session` with the `params.mongodb`:

```js
import { ObjectID } from 'mongodb'

export default async app => {
app.use('/fooBarService', {
async create(data) {
// assumes you have access to the mongoClient via your app state
let session = app.mongoClient.startSession()
try {
await session.withTransaction(async () => {
let fooID = new ObjectID()
let barID = new ObjectID()
app.service('fooService').create(
{
...data,
_id: fooID,
bar: barID,
},
{ mongodb: { session } },
)
app.service('barService').create(
{
...data,
_id: barID
foo: fooID
},
{ mongodb: { session } },
)
})
} finally {
await session.endSession()
}
}
})
}
```

## Example

Here is an example of a Feathers server with a `messages` endpoint that writes to the `feathers` database and the `messages` collection.

```
$ npm install @feathersjs/feathers @feathersjs/errors @feathersjs/express @feathersjs/socketio feathers-mongodb mongodb
```

In `app.js`:

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

const MongoClient = require('mongodb').MongoClient;
const service = require('feathers-mongodb');

// 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
app.configure(socketio());

// Connect to the db, create and register a Feathers service.
app.use('/messages', service({
paginate: {
default: 2,
max: 4
}
}));

// A basic error handler, just like Express
app.use(express.errorHandler());

// Connect to your MongoDB instance(s)
MongoClient.connect('mongodb://localhost:27017/feathers')
.then(function(client){
// Set the model now that we are connected
app.service('messages').Model = client.db('feathers').collection('messages');

// Now that we are connected, create a dummy Message
app.service('messages').create({
text: 'Message created on server'
}).then(message => console.log('Created message', message));
}).catch(error => console.error(error));

// Start the server.
const port = 3030;

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

Run the example with `node app` and go to [localhost:3030/messages](http://localhost:3030/messages).

## Querying

Additionally to the [common querying mechanism](https://docs.feathersjs.com/api/databases/querying.html) this adapter also supports [MongoDB's query syntax](https://docs.mongodb.com/v3.2/tutorial/query-documents/) and the `update` method also supports MongoDB [update operators](https://docs.mongodb.com/v3.2/reference/operator/update/).

> **Important:** External query values through HTTP URLs may have to be converted to the same type stored in MongoDB in a before [hook](https://docs.feathersjs.com/api/hooks.html) otherwise no matches will be found. Websocket requests will maintain the correct format if it is supported by JSON (ObjectIDs and dates still have to be converted).

For example, an `age` (which is a number) a hook like this can be used:

```js
const ObjectID = require('mongodb').ObjectID;

app.service('users').hooks({
before: {
find(context) {
const { query = {} } = context.params;

if(query.age !== undefined) {
query.age = parseInt(query.age, 10);
}

context.params.query = query;

return Promise.resolve(context);
}
}
});
```

Which will allows queries like `/users?_id=507f1f77bcf86cd799439011&age=25`.

## Collation Support

This adapter includes support for [collation and case insensitive indexes available in MongoDB v3.4](https://docs.mongodb.com/manual/release-notes/3.4/#collation-and-case-insensitive-indexes). 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'`.

```js
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.

```js
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](https://docs.mongodb.com/manual/reference/collation/).

## License

Copyright (c) 2019

Licensed under the [MIT license](LICENSE).