我使用Sequelize.js进行ORM并且有一些关联(现在实际上并不重要)。我的模型从这些关联中获取get
和set
方法。像这样(来自文档):
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对象)并创建新模型,其中包含所有信息。我应该能够更新它们中缺少的部分(来自关系)。
答案 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关于如何理解该怎么做的合作:)