通用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(可选) - 一个 分页对象 包含一个default和max页面大小whitelist(可选) - 允许的其他非标准查询参数列表 (e.g[ '$regex', '$populate' ])multi(可选, 默认:false) - 允许带有数组的create和带有null的update和remove来改变多个项目.对于所有方法或一组允许的方法都可以是true(e.g.[ 'remove', 'create' ])
分页¶
初始化适配器时,可以在 paginate 对象中设置以下分页选项:
default- 设置未设置$limit时的默认项目数max- 设置每页允许的最大项数(即使$limit查询参数设置得更高)
当设置 paginate.default 时, find 将返回以下形式的 页面对象 (而不是正常数组):
{
"total": "<total number of records>",
"limit": "<max number of items per page>",
"skip": "<number of skipped items (offset)>",
"data": [/* data */]
}
分页选项可以设置如下:
const service = require('feathers-<db-name>');
// Set the `paginate` option during initialization
app.use('/todos', service({
paginate: {
default: 5,
max: 25
}
}));
// override pagination in `params.paginate` for this call
app.service('todos').find({
paginate: {
default: 100,
max: 200
}
});
// disable pagination for this call
app.service('todos').find({
paginate: false
});
注解
客户端中不提供禁用或更改默认分页的功能.只有 params.query 被传递给服务器(另见 这里 的解决方法)
小技巧
要获得可用记录的数量,将 $limit 设置为 0.这只会对数据库运行(快速)计数查询.
服务方式¶
本节介绍如何为所有适配器实现 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) - > Promise 将 id 标识的记录与 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.
钩子¶
最灵活的选择是通过以下方式编织功能 钩子.例如,可以像这样添加 createdAt 和 updatedAt 时间戳:
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
}
}));