Sequelize.js - 如何从关联中正确使用get方法(每次调用都没有sql查询)?

时间:2015-05-12 09:50:41

标签: node.js orm sequelize.js

我使用Sequelize.js进行ORM并且有一些关联(现在实际上并不重要)。我的模型从这些关联中获取getset方法。像这样(来自文档):

var User = sequelize.define('User', {/* ... */})
var Project = sequelize.define('Project', {/* ... */})

// One-way associations
Project.hasOne(User)

/*
...
Furthermore, Project.prototype will gain the methods getUser and setUser
according to the first parameter passed to define.
*/

现在,我有Project.getUser(),它返回一个Promise。但是如果我在同一个对象上调用两次,我会执行两次SQL查询。

我的问题是 - 我错过了什么,或者这是预期的行为?实际上,每次在此对象上调用相同的方法时,我都不想进行其他查询。

如果这是预期的 - 我是否应该使用带有成员变量的自定义getter,我手动填充并返回(如果存在)?还是有更聪明的东西? :)

更新 从DeBuGGeR的回答 - 我知道我可以在进行查询时使用includes以便急切地加载所有内容,但我根本不需要它,我无法做到这一点每时每刻。如果我在开始时加载我的整个数据库,只是为了理解(通过一些标准)我不会需要它,这会浪费资源并且开销很大。我想根据情况做出额外的查询。但我也无法销毁我拥有的所有模型(DAO对象)并创建新模型,其中包含所有信息。我应该能够更新它们中缺少的部分(来自关系)。

2 个答案:

答案 0 :(得分:5)

如果您使用getUser(),它将进行查询调用,它会让您访问该用户。您可以手动将其保存到project.user或project.users,具体取决于关联。

但你可以试试Eager Loading

Project.find({
  include: [
    { model: User, as: 'user' } // here you HAVE to specify the same alias as you did in your association
  ]
}).success(function(project){
project.user // contains the user

});

例如getUser()。不要指望它会自动缓存用户并且不要巧妙地覆盖它,因为它会产生副作用。 getUser应该从数据库获取,它应该!

Project.getUser().then(function(user){
   // user is available and is a sequelize object
   project.user = user; // save project.user and use it till u want to
})

答案 1 :(得分:1)

事情的第一部分很清楚 - 每次调用get[Association](例如Project.getUser() WILL 会导致数据库查询。

Sequelize不会保留任何类型的状态,也不会缓存结果。您可以在调用的Promisified结果中获得user,但如果您想再次使用它,则必须进行另一次查询。

@DeBuGGeR所说的 - 关于使用访问器也是不正确的 - 访问者仅在查询后立即出现,并且不会被保留。

有时候这不行,你必须自己实现某种缓存系统。这是棘手的部分:

IF 你想使用相同的get方法Project.getUser(),你将无法做到,因为Sequelize会覆盖你的instanceMethods。例如,如果您拥有上述关联,则此将无效

instanceMethods: {
    getUser: function() {
        // check if you have it, otherwise make a query
    }
}

有几种可能的方法可以解决它 - 或者稍微更改Sequelize core(首先检查方法是否存在),或者对这些函数使用某种包装。

有关此内容的更多详情,请访问:https://github.com/sequelize/sequelize/issues/3707

感谢mickhansen关于如何理解该怎么做的合作:)