Orm 如何在sailsjs控制器中运行多个查询?
在sailsjs中,一次只能运行和传递一组查询数据。例如,这里是我的主页的控制器:Orm 如何在sailsjs控制器中运行多个查询?,orm,sails.js,Orm,Sails.js,在sailsjs中,一次只能运行和传递一组查询数据。例如,这里是我的主页的控制器: module.exports = { index: function (req, res) { Blog.find() .limit(3) .sort('createdAt desc') .where({ isPublished: 1 }) .exec(function(err, posts) {
module.exports = {
index: function (req, res) {
Blog.find()
.limit(3)
.sort('createdAt desc')
.where({ isPublished: 1 })
.exec(function(err, posts) {
if (err) return next(err);
res.view({
layout: "homeLayout",
posts:posts
});
});
}
};
我如何从其他模型中查询数据,并将其与我已经传递的博客数据一起传递给我的视图?我已经想出了一些方法来实现这一点。第一种方法是嵌套查询,例如
Blog.find()
.limit(30)
.sort('createdAt desc')
.where({ isPublished: 1 })
.exec(function(err, posts) {
SomeOtherModel.find()
.limit(5)
.sort('createdAt desc')
.where({ isPublished: 1 })
.exec(function(err, otherdata) {
res.view({
posts: posts,
otherdata: otherdata
});
});
});
第二种方法是使用承诺(我以前不知道这一点)
第三种方法(我最后使用了这种方法)是创建一个策略(特定于sailsjs,但它是express中间件)
这样做您不需要向视图传递任何内容,但是我不确定向响应对象随机添加数据是否是一种好的做法。您可以使用承诺来实现这一点。这实际上是一个很好的用例。 我使用,这是(赛欧的ORM)在幕后使用的 您可以在下面看到一个代码示例,其中我从第一个模型检索数据,然后使用检索到的数据查询其他模型以获取更多数据(并行),最后将结果发送回视图
SomeModel.findOne(标准)。然后(函数(结果){
所有人([
SomeOtherModel.getSomething(结果),
YetAnotherModel.getSomethingElse(结果)
]).spread(函数(someOtherResult,yetAnotherResult){
风险值数据={
事情:结果,
材料:其他结果,
其他事物:yetAnotherResult
};
返回res.view(数据);
});
}).失败(功能(原因){
返回res.view(原因);
});
getSomething()
函数应该返回一个承诺,来自Sails的标准查找器将透明地工作(只是不要通过回调)。标准查找器的行为似乎与Q承诺不完全一样,我在这里给出的答案应该有助于获得更一致的行为
您也可以使用async.auto(见下文)。下面是一个完整的sails回购示例
var async = require('async'),
_ = require('lodash');
module.exports = {
index: function (req, res) {
async.auto({
// Get the blog posts
posts: function (cb) {
Blog.find()
.where({ isPublished: 1 })
.limit(5)
.sort('createdAt DESC')
.exec(cb);
},
// Get some more stuff
// (this will happen AT THE SAME TIME as `posts` above)
otherThings: function (cb) {
OtherThing.find()
.limit(30)
.exec(cb);
},
// Get comments
// (we'll wait until `posts` is finished first)
comments: ['posts', function (cb, async_data) {
// Get `posts`
// (the second argument to cb() back in `posts`)
// Used map to make sure posts are an array of ids and not just an object.
var posts = async_data.posts.map(function (item){ return item.id});
// Get comments that whose `post_id` is equal to
// the id of one of the posts we found earlier
Comment.find()
.where({ post_id: posts })
.exec(cb);
}]
},
function allDone (err, async_data) {
// If an error is passed as the first argument to cb
// in any of the functions above, then the async block
// will break, and this function will be called.
if (err) return res.serverError(err);
var posts = async_data.posts;
var comments = async_data.comments;
var otherThings = async_data.otherThings;
// Fold the comments into the appropriate post
// An in-memory join
_.map(posts, function (post) {
var theseComments =
_.where(comments, { post_id: post.id });
post.comments = theseComments;
});
// Show a view using our data
res.json({
// layout: 'homeLayout',
posts: posts,
otherThings: otherThings
});
});
}
};
因此,以下是如何发出3个请求并将其所有数据传递到视图中: 第一次安装Q
npm install q
然后使用下面的代码,用您的模型替换我的模型:
// first import Q
var Q = require('q');
// Let's combine results of 3 queries
Q.all([
// let's find one user with name "Pavel"
User.findOne({name: 'Pavel'}).then(),
// let's find one Lexus car
Cars.findOne({brand: 'Lexus'}).then(),
// Finally let's get the first Apple phone
Phones.findOne({brand: 'Apple'}).then()
])
.spread(function (user, car, phone) {
// Output results as json, but you can do whatever you want here
res.json([user, car, phone]);
}).fail(function (reason) {
// output reason of failure
res.json(reason);
});
有相当多的讨论正在进行,以摆脱Q库,而不是使此可插拔,如ES6承诺、蓝鸟等。请参阅:@Arceldon是的,我是关于Waterline的一个老讨论的一部分:但它从未被合并。Sails的团队对性能和承诺总体上感觉不太好。@Arceldon事实上,他们刚刚合并了另一个pull请求:是的,在我关注github回购协议时看到了这一点。聊天结束后准时:)如果请求是独立的,Bluebird是很棒的或异步并行的
npm install q
// first import Q
var Q = require('q');
// Let's combine results of 3 queries
Q.all([
// let's find one user with name "Pavel"
User.findOne({name: 'Pavel'}).then(),
// let's find one Lexus car
Cars.findOne({brand: 'Lexus'}).then(),
// Finally let's get the first Apple phone
Phones.findOne({brand: 'Apple'}).then()
])
.spread(function (user, car, phone) {
// Output results as json, but you can do whatever you want here
res.json([user, car, phone]);
}).fail(function (reason) {
// output reason of failure
res.json(reason);
});