通用API

所有数据库适配器都实现了用于初始化,分页,扩展和查询的通用接口.本章介绍常见的适配器初始化和选项,如何启用和使用分页,有关特定服务方法的行为以及如何使用自定义功能扩展适配器的详细信息.

重要

每个数据库适配器都是 服务 的实现.我们建议在使用数据库适配器之前熟悉服务,服务事件和挂钩.

service([options])

返回使用给定选项初始化的新服务实例.

const service = require('feathers-<adaptername>');

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

选项:

  • id (可选) - id字段属性的名称(通常默认设置为 id_id).

  • events (可选) - 此服务发送的 自定义服务事件 列表

  • paginate (可选) - 一个 分页对象 包含一个 defaultmax 页面大小

  • whitelist (可选) - 允许的其他非标准查询参数列表 (e.g [ '$regex', '$populate' ])

  • multi (可选, 默认: false) - 允许带有数组的 create 和带有 nullupdateremove 来改变多个项目.对于所有方法或一组允许的方法都可以是 true (e.g. [ 'remove', 'create' ])

服务方式

本节介绍如何为所有适配器实现 services 的细节.

adapter.Model

如果ORM或数据库支持模型,则可以在 adapter.Model 中找到模型实例或属于此适配器的集合的引用.这允许使用该模型轻松地进行自定义查询,例如,在钩子里:

// Make a MongoDB aggregation (`messages` is using `feathers-mongodb`)
app.service('messages').hooks({
  before: {
    async find(context) {
      const results = await service.Model.aggregate([
        { $match: {item_id: id} }, {
          $group: {_id: null, total_quantity: {$sum: '$quantity'} }
        }
      ]).toArray();

      // Do something with results

      return context;
    }
  }
});

adapter.find(params)

adapter.find(params) - > Promise 返回与查询匹配的所有记录的列表 查询. 如果启用了 pagination,将返回带结果的数组或页面对象.

重要

通过REST URL使用时,所有查询值都是字符串.根据数据库,``params.query`` 中的值可能必须在 钩子 中转换为正确的类型.

// Find all messages for user with id 1
app.service('messages').find({
  query: {
    userId: 1
  }
}).then(messages => console.log(messages));

// Find all messages belonging to room 1 or 3
app.service('messages').find({
  query: {
    roomId: {
      $in: [ 1, 3 ]
    }
  }
}).then(messages => console.log(messages));

查找ID为1的用户的所有消息

GET /messages?userId=1

查找属于房间1或3的所有邮件

GET /messages?roomId[$in]=1&roomId[$in]=3

adapter.get(id, params)

adapter.get(id, params) -> Promise 通过其唯一标识符(初始化期间在 id 选项中设置的字段)检索单个记录.

app.service('messages').get(1)
  .then(message => console.log(message));
GET /messages/1

adapter.create(data, params)

adapter.create(data, params) -> Promise 使用 data 创建一个新记录. data 也可以是一个用来创建多个记录的数组.

app.service('messages').create({
    text: 'A test message'
  })
  .then(message => console.log(message));

app.service('messages').create([{
    text: 'Hi'
  }, {
    text: 'How are you'
  }])
  .then(messages => console.log(messages));
POST /messages
{
  "text": "A test message"
}

adapter.update(id, data, params)

adapter.update(id,data,params) - > Promise 完全用 data 替换 id 标识的单个记录.不允许替换多个记录(id 不能是 null). id 无法更改.

app.service('messages').update(1, {
    text: 'Updates message'
  })
  .then(message => console.log(message));
PUT /messages/1
{ "text": "Updated message" }

adapter.patch(id, data, params)

adapter.patch(id,data,params) - > Promiseid 标识的记录与 data 合并. id 可以是 null 以允许替换多个记录(所有匹配 params.query 的记录与 .find 中相同). id 无法更改.

app.service('messages').patch(1, {
  text: 'A patched message'
}).then(message => console.log(message));

const params = {
  query: { read: false }
};

// Mark all unread messages as read
app.service('messages').patch(null, {
  read: true
}, params);
PATCH /messages/1
{ "text": "A patched message" }

将所有未读邮件标记为已读

PATCH /messages?read=false
{ "read": true }

adapter.remove(id, params)

adapter.remove(id, params) -> Promise 删除由 id 标识的记录. id 可以是 null 以允许删除多个记录(所有与``params.query``匹配的记录与 .find 相同).

app.service('messages').remove(1)
  .then(message => console.log(message));

const params = {
  query: { read: true }
};

// Remove all read messages
app.service('messages').remove(null, params);
DELETE /messages/1

删除所有阅读邮件

DELETE /messages?read=true

扩展适配器

有两种方法可以扩展现有的数据库适配器.通过扩展ES6基类或通过钩子添加功能.

小技巧

请记住,调用原始服务方法将返回一个使用该值解析的Promise.

钩子

最灵活的选择是通过以下方式编织功能 钩子.例如,可以像这样添加 createdAtupdatedAt 时间戳:

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

// Import the database adapter of choice
const service = require('feathers-<adapter>');

const app = feathers().use('/todos', service({
  paginate: {
    default: 2,
    max: 4
  }
}));

app.service('todos').hooks({
  before: {
    create: [
      (context) => context.data.createdAt = new Date()
    ],

    update: [
      (context) => context.data.updatedAt = new Date()
    ]
  }
});

app.listen(3030);

Classes (ES6)

所有模块还导出一个 ES6类 作为 Service, 可以像这样直接扩展:

'use strict';

const { Service } = require( 'feathers-<database>');

class MyService extends Service {
  create(data, params) {
    data.created_at = new Date();

    return super.create(data, params);
  }

  update(id, data, params) {
    data.updated_at = new Date();

    return super.update(id, data, params);
  }
}

app.use('/todos', new MyService({
  paginate: {
    default: 2,
    max: 4
  }
}));