Feathers数据库适配器是一些模块,它们使用通用API进行初始化和设置并提供通用查询语法,从而为特定数据库提供实现标准CRUD功能的服务。
重要: 服务允许实现对任何数据库的访问,此处列出的数据库适配器只是具有通用API的便捷包装器。您仍然可以为此处未列出的数据库获取Feathers功能。另请参阅社区数据库适配器列表
支持以下数据库:
数据库 | 适配器 |
---|---|
在内存中 | feathers-memory,feathers-nedb |
Localstorage,AsyncStorage | feathers-localStorage |
文件系统 | feathers-nedb |
MongoDB | feathers-mongodb,feathers-mongoose |
MySQL,PostgreSQL,MariaDB,SQLite,MSSQL | feathers-knex,feathers-sequelize |
Elasticsearch | feathers-elasticsearch |
Objection | feathers-objection |
通用API
所有数据库适配器都实现了用于初始化,分页,扩展和查询的通用接口。本章介绍常见的适配器初始化和选项,如何启用和使用分页,有关特定服务方法的行为以及如何使用自定义功能扩展适配器的详细信息。
重要说明:每个数据库适配器都是Feathers服务接口的实现。我们建议在使用数据库适配器之前熟悉服务,服务事件和挂钩。
初始化
每个适配器都导出一个Service
可以导出和扩展的类。
const { Service } = require('feathers-');
app.use('/messages', new Service());
app.use('/messages', new Service({ id, events, paginate }));
选项
-
id
(可选) - id字段属性的名称(通常默认设置为id
或_id
)。 -
events
(可选) - 此服务发送的自定义服务事件列表 -
paginate
(可选) -甲分页对象含有default
与max
页大小 -
whitelist
(可选) - 允许的其他非标准查询参数列表(例如[ '$regex', '$populate' ]
) -
multi
(可选,默认值false
:) - 允许create
使用数组update
和remove
使用idnull
更改多个项目。可以true
用于所有方法或允许方法的数组(例如[ 'remove', 'create' ]
)
分页
初始化适配器时,您可以在paginate对象中设置以下分页选项:
- default- 设置$limit未设置时的默认项目数
- max- 设置每页允许的最大项数(即使$limit查询参数设置得更高)
当paginate.default被设置时,find将返回一个页面对象(而不是正常的数组)的形式如下:
{
"total": "",
"limit": "",
"skip": "",
"data": [/* data */]
}
分页选项可以设置如下:
const service = require('feathers-');
// 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。这只会对数据库运行(快速)计数查询。
扩展适配器
有两种方法可以扩展现有的数据库适配器。通过扩展ES6基类或通过钩子添加功能。
ProTip:请记住,调用原始服务方法将返回一个使用该值解析的Promise。
Class ES6
所有模块也导出ES6类,因为Service
它可以像这样直接扩展:
'use strict';
const { Service } = require( 'feathers-');
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
}
}));
Hooks
另一种选择是通过钩子增加功能。例如,createdAt
和updatedAt
时间戳可以加入这样的:
const feathers = require('@feathersjs/feathers');
// Import the database adapter of choice
const service = require('feathers-');
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);
Service 的方法
constructor(options)
初始化新服务。super(options)覆盖时应该调用。
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``params.query
使用公共查询机制返回与查询匹配的所有记录的列表。如果启用了分页,将返回包含结果的数组或页面对象。
重要提示:通过REST URL使用时,所有查询值都是字符串。根据数据库的不同,
params.query
可能必须在before挂钩中将值转换为正确的类型。
// 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
完全取代由标识的单个记录id
用data
。不允许替换多个记录(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
in 匹配.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