所以我开发了一个带有feathers框架的应用程序。 我有一个连接到数据库服务的钩子,我想从另一个服务访问数据。 这可能吗,而且容易吗? 我希望该服务能够访问多个 neDB 文件。 我该怎么做呢?
'use strict';
module.exports = function(options) {
return function(hook) {
// access other db files here and get data
hook.data = {
putDataHere: newData
};
};
};
是的。 看一下如何获取相关项目的hook.app.service('servicename')
访问另一个服务并调用您需要的方法。 对于等待的钩子,您可以返回一个 Promise(用hook
对象解析),这很方便,所有服务方法都已经这样做了:
module.exports = function(options) {
return function(hook) {
return hook.app.service('otherservice').find({
query: { name: 'David' }
}).then(page => {
const davids = page.data;
hook.data.davids = davids;
// Or you can replace all the data with
hook.data = { davids };
// IMPORTANT: always return the `hook` object in the end
return hook;
});
};
};
@daffl非常感谢。 我认为这很容易,但在文档中找不到它,我一定是错过了。
好的,这是一个查找调用,我在钩子之前有这个(如果您需要该信息)
我只有 25 个,但有数百个。 如果我取消限制,我只会得到 5 个项目。
这是怎么回事,我如何得到所有?
module.exports = function(options) {
return function(hook) {
const dataSet = hook.params.query.dataSet;
const userVector = hook.params.query.userVector;
return hook.app.service('data').find({
query: { dataSet: dataSet, $limit:2000 }
}).then(page => {
// lots of magic here
//console.log(page.data);
hook.result = page.data;
return hook;
});
};
};
这取决于您在配置中为paginate.max
设置的选项。 这是一种保护措施,因此某人不能只是远程请求数百万条记录。 在所有较新的适配器中,您可以关闭分页以获取所有记录,如下所示:
return hook.app.service('data').find({
paginate: false,
query: { dataSet: dataSet }
}).then(data => {
// data is an array
});
当我这样做时,我得到 0 条记录。 当我删除分页时:false 我得到 25。
npm ls feathers-nedb
显示 v2.4.1 吗? 如果不是,您可能需要相应地更新您的package.json
。
我刚刚验证了paginate: false
可以与以下示例一起使用:
const feathers = require('feathers');
const rest = require('feathers-rest');
const socketio = require('feathers-socketio');
const hooks = require('feathers-hooks');
const nedb = require('feathers-nedb');
const bodyParser = require('body-parser');
const handler = require('feathers-errors/handler');
const NeDB = require('nedb');
// A Feathers app is the same as an Express app
const app = feathers();
const db = new NeDB({
filename: './data/messages.db',
autoload: true
});
// Parse HTTP JSON bodies
app.use(bodyParser.json());
// Parse URL-encoded params
app.use(bodyParser.urlencoded({ extended: true }));
// Register hooks module
app.configure(hooks());
// Add REST API support
app.configure(rest());
// Configure Socket.io real-time APIs
app.configure(socketio());
// Register our memory "users" service
app.use('/todos', nedb({
Model: db,
paginate: {
default: 20,
max: 50
}
}));
// Register a nicer error handler than the default Express one
app.use(handler());
const promises = [];
for(let i = 0; i < 700; i++) {
promises.push(app.service('todos').create({ text: `Item #${i}`}));
}
Promise.all(promises).then(function() {
app.service('todos').find({
paginate: false,
query: {}
}).then(data => console.log(data));
});
// Start the server
app.listen(3333);
我将 700 个项目记录到控制台。 您是否不小心在查询中添加了paginate: false
而不是主要参数?
这就是我所做的:
'use strict';
module.exports = function(options) {
return function(hook) {
const dataSet = hook.params.query.dataSet;
const userVector = hook.params.query.userVector;
return hook.app.service('data').find({
paginate: false,
query: { dataSet: dataSet, $limit:2000 }
}).then(page => {
// lots of magic here
console.log(page.data);
hook.result = page.data;
return hook;
});
};
};
仍然得到 0 个结果和 25 个没有分页变量的结果和 5 个没有限制的结果。
但是,我得到了它的工作:
'use strict';
module.exports = function(options) {
return function(hook) {
const dataSet = hook.params.query.dataSet;
const userVector = hook.params.query.userVector;
return hook.app.service('data').find({
paginate: false,
query: { dataSet: dataSet }
}).then(page => {
// lots of magic here
console.log(page);
hook.result = page;
return hook;
});
};
};
如您所见,结果不再在 page.data 中,而仅在 page 变量中。
学过的知识 :)
哦,谢谢@daffl的帮助。
在客户端它不起作用。 ( paginate: false,
变量)。
只有query
在客户端和服务器之间传递。 我会尽量避免让客户端请求所有内容(如果您的数据库有一百万条记录,它将同时杀死服务器和客户端)。 如果没有办法解决它,您必须将一个特殊的查询参数(例如$paginate
)从params.query
映射到服务器上的钩子中的params
中:
app.service('data').before({
find(hook) {
if(hook.params.query && hook.params.query.$paginate) {
hook.params.paginate = hook.params.query.$paginate === 'false' || hook.params.query.$paginate === false;
delete hook.params.query.$paginate;
}
}
});
我理解不允许在客户端进行分页的警告,但是,我正在制作的工具仅供我在本地运行。 再次感谢您所做的一切。
@daffl嗨,我正在使用您发布的代码来检索用户的帖子。
module.exports = function(options) {
return function(hook) {
// hook.getPosts = true;
const id = hook.result.id;
console.log("id");
return hook.app.service('posts').find({
paginate: false,
query: { postedBy: id }
}).then(function(posts){
console.log("posts");
// Set the posts on the user property
hook.result.posts = posts.data;
// Always return the hook object or `undefined`
return hook;
});
};
};
但这会导致服务器进入无限循环,节点应用程序最终崩溃。
我使用 MySQL 作为通过 sequelize 连接的数据库。
我究竟做错了什么?
我已经为帖子设置了一个类似的钩子,以根据postedBy
字段填充用户字段。 所以看起来,用户钩子会触发后钩子,这反过来又会触发原始用户钩子,循环继续导致无限循环和内存溢出。
如何仅填充浅层相关项目的任何想法,即,钩子将仅拉动第一层上的相关项目。
@daffl您的想法很棒,尽管代码不起作用。
我不得不将 hook.paginate 更改为 hook.params.paginate 以使其工作。
我做了一点改动,这样你就可以在那里发送任何你想要的东西。
所以你可以 $paginate : {value: false} 禁用分页或
$paginate: { value: {default: 100, max: 2000}} 覆盖分页
app.service('data').before({
find(hook) {
if(hook.params.query.$paginate) {
hook.params.paginate = hook.params.query.$paginate.value;
delete hook.params.query.$paginate;
}
}
});
要考虑的另一件事是,当分页禁用时,数据不在 res.data 中,而是在 res 本身中。
@fortunes-technology 你是对的。 我更新了我的代码片段。 这应该有效:
app.service('data').before({
find(hook) {
if(hook.params.query && hook.params.query.$paginate) {
hook.params.paginate = hook.params.query.$paginate === 'false' || hook.params.query.$paginate === false;
delete hook.params.query.$paginate;
}
}
});
我认为如果 $paginate 设置为 false(这是这个钩子的重点,禁用它...),if 也将是 false。 或许
app.service('data').before({
find(hook) {
if(hook.params.query && hook.params.query.hasOwnProperty('$paginate')) {
hook.params.paginate = hook.params.query.$paginate === 'false' || hook.params.query.$paginate === false;
delete hook.params.query.$paginate;
}
}
});
你好呀。 有人能告诉我羽毛服务是否有 findOne 功能或如何实现它? 谢谢!
抄送@daffl
findOne
只是find
的$limit
为 1:
app.service('myservice').find({ query: { name: 'test', $limit: 1 } })
.then(page => page.data[0])
.then(result => console.log('Got', result);
@daffl我问是因为猫鼬有 findOne 并且我建议如果已经找到了一些东西,它不会搜索所有其余的集合。 所以,我认为 findOne 比使用 limit=1 搜索更智能......这就是我问的原因。
我通常这样做是为了快速找到一个:
const employee = (await context.app.service('employees').find({ query: { userId: user.id }, paginate: false }))[0];
我刚刚为.findOne()
方法制作了一个插件: feathers-findone
我找不到有关如何为客户端添加 $paginate 解决方法的任何示例。 所以我创建了一个从 app.hooks.js 文件运行的 before 钩子,并做了一些修改:
module.exports = function () {
return context => {
if (context.params.query && hook.params.query.hasOwnProperty('$paginate')) {
context.params.paginate = context.params.query.$paginate === 'false' || context.params.query.$paginate === false;
delete context.params.query.$paginate;
}
};
};
您将如何为此编写单元或集成测试?
所以如果我的钩子中有以下内容
const records = getItems(context);
records.authors = await context.app.service('users') .find({ query: { _id: { $in: records.authorIds } } }, context.params);
我如何在我的单元测试中“模拟”context.app.service?
我需要将它添加到我的 contextBefore 对象中吗?
contextBefore = {
type: 'before',
params: { provider: 'socketio', user: { _id: 1 } },
data: {
_id: 1,
},
};
我正在使用由feathers-plus 生成器生成的单元测试自动。
https://generator.feathers-plus.com/get-started/#unit -test-for-a-hook
还是我应该改用集成测试?
我前段时间走的是嘲讽路线。 我认为这是一个非常糟糕的主意。 您最终将不得不嘲笑越来越多的 Feathers。 不能保证你的模拟功能像羽毛一样,你可能会得到假阴性,就像我一样。
实例化 Feathers 应用程序非常快,因此请使用 Feathers 而不是模拟。 这就是 cli+ 测试的方法。
我写了一篇文章提到了这一点。 https://medium.com/feathers-plus/automatic-tests-with-feathers-plus-cli-4844721a29cf
谢谢 eddyy,我已经看到了,很棒的文章,真的很有帮助。
我一直在苦苦思索如何将应用程序添加到我的上下文对象中,但最终还是解决了,我想!
const app = feathers();
contextBefore = {
type: 'before',
params: { provider: 'socketio', user: { _id: 1 } },
data: {
_id: 1,
},
app,
};
然后我不得不修改测试,以便它使用异步。
it('patch test', async () => {
contextBefore.app.use('users', {
async find() {
return { data: [ { expectedResultObj1 }, { expectedResultObj2 } ] };
}
});
contextBefore.data = {
_id: 1,
};
assert(true);
await hookToTest()(contextBefore);
assert.deepEqual(contextBefore.data, {
_id: 1,
expectedResultObject1,
expectedResultObject2,
});
});
这是正确的方法还是有更好的方法?
看起来挺好的
@fortunes-technology 你是对的。 我更新了我的代码片段。 这应该有效:
app.service('data').before({ find(hook) { if(hook.params.query && hook.params.query.$paginate) { hook.params.paginate = hook.params.query.$paginate === 'false' || hook.params.query.$paginate === false; delete hook.params.query.$paginate; } } });
也可以使用查询 $limit : null 绕过
最有用的评论
是的。 看一下如何获取相关项目的
hook.app.service('servicename')
访问另一个服务并调用您需要的方法。 对于等待的钩子,您可以返回一个 Promise(用hook
对象解析),这很方便,所有服务方法都已经这样做了: