2016-10-06 37 views
1

我是nodejs和Loopback/Express的新手。我试图编写一个涉及API调用的简单应用程序,它有多个相关模型的db请求,但我没有找到任何相关的文档或示例来说明这一点。远程方法中的相关模型的多个查询

想象一下3个模型:作者,发布和评级。每篇文章有一个作者,并拥有许多评级。评级有一个称为'星星'的整数值。

我创建的帖子被称为“细节”,这应该返回以下所有的自定义API remoteMethod:

  • 帖子详细介绍
  • 作者的详细信息(存储在相关作者机型)
  • 具有分相关评分数目== 1
  • 具有分相关评分数目== 2
  • 相关评分数目具有分== 3

什么是最好的方式来实现这个最低和更平行的数据库查询?我已经使用Promises尝试了以下代码,但本质上这是一个效率低下的同步代码,它会对数据库进行多次不必要的查询,并且它很快变得非常混乱。

Post.details = function(id, cb) { 

var LoopBackContext = require('loopback-context'); 
var app = require('../../server/server'); 
var Author = app.models.Author; 
var Rating = app.models.Rating; 

var response = {post: null, 
       author: null, 
       ratings_0: null, 
       ratings_1: null, 
       ratings_2: null 
    }; 

Post.findById(id, {include: 'author', where: {deleted: false}}) 
    .then(function(p) { 
     response.post = p; 
     return Author.findById(p.authorId); 
    }) 
    .then(function(r) { 
     response.author = r; 
     return Rating.find({where: {postId: id, stars: 0}}); 
    }) 
    .then(function(r) { 
     response.votes_0 = r.length; 
     return Rating.find({where: {postId: id, stars: 1}}); 
    }) 
    .then(function(r) { 
     response.votes_1 = r.length; 
     return Rating.find({where: {postId: id, stars: 2}}); 
    }) 
    .then(function(r) { 
     response.votes_2 = r.length; 
     cb(null, response); 
    }); 

    }; 

这对于这样一件小事来说太过分了。我也尝试在查询中使用'include',但它也变得很难使用,并且它不支持Loopback中的二级过滤器。

实现此目的的最佳方式是什么?

+0

您可以与Promise.all同时处理所有这些请求 –

回答

1

那么一点点的重构和改变,这将是非常简短易懂:

Post.details = function(id) { 
    var app = require('../../server/server'); 
    var Rating = app.models.Rating; 

    return Promise.all([ 
    Post.findById(id, {include: 'author', where: {deleted: false}}), 
    Rating.count({ where: {postId: id, stars: 0}}), 
    Rating.count({ where: {postId: id, stars: 1}}), 
    Rating.count({ where: {postId: id, stars: 2}}), 
    ]).then([post, ratings_0, ratings_1, ratings_2]) => { 
    return { 
     post, 
     author: post.author, 
     ratings_0, 
     ratings_1, 
     ratings_2, 
    }; 
    }); 
}; 

有几件事情怎么回事:

  • 你不需要Author.findById,假设include: 'author'涵盖它。
  • 至于收视率方面,您刚刚使用了Rating.count方法。由于使用的带宽较少,并且数据库可以更快地提供数据,所以它会更快,因为它将直接从索引提供。
  • 我已经使用ES6破坏,对象字面速记和箭头功能。
  • 如果您在回送远程方法中返回承诺,它将使用请求响应的方法返回值而不是回调。
  • Promise.all将并行运行查询,并在所有给定查询完成时结束。