Sails.js – 使用多个连接获取对象(模型)

我是新的node.js和更新到Sails.js框架。

我目前正在试图使用我的数据库,我不明白Sails.js的所有事情,但我设法按步骤做我想做的事情。 (我习惯了一些PHP MVC框架,所以不难理解结构。)

在这里,我试图从我的数据库中获取一行,使用2 JOIN子句。 我设法使用SQLModel.query()函数来做到这一点,但我想以“更清洁”的方式来做到这一点。

所以我有我的数据库中的3个表:meta,lang和meta_lang。 这很简单,画面比文字好,这里有一些截图。

元表

lang表

meta_lang

meta_lang表

我想要做的是得到meta_table中与' meta_table和' meta_table (例如)匹配的行。

这里是Meta和Lang模型(我用sails generate model命令,并用我需要的编辑它们):

 module.exports = { attributes: { code : { type: 'string' }, metaLangs:{ collection: 'MetaLang', via: 'meta' } } }; 

 module.exports = { attributes: { code : { type: 'string' }, metaLangs:{ collection: 'MetaLang', via: 'lang' } } }; 

这里是我的MetaLang模型,我创build了3个函数来testing几种方法。 第一个函数findCurrent完美地工作,但正如你所看到的,我必须编写SQL。 这是我想要避免的,如果可能的话,我觉得它更干净(我想尽可能经常使用Sails.js工具)。

 module.exports = { tableName: 'meta_lang', attributes: { title : { type: 'string' }, description : { type: 'text' }, keywords : { type: 'string' }, meta:{ model:'Meta', columnName: 'meta_id' }, lang:{ model:'Lang', columnName: 'lang_id' } }, findCurrent: function (metaCode, langCode) { var query = 'SELECT ml.* FROM meta_lang ml INNER JOIN meta m ON m.id = ml.meta_id INNER JOIN lang l ON l.id = ml.lang_id WHERE m.code = ? AND l.code = ?'; MetaLang.query(query, [metaCode, langCode], function(err, metaLang) { console.log('findCurrent'); if (err) return console.log(err); console.log(metaLang); // OK this works exactly as I want (I would have prefered a 'findOne' result, only 1 object instead of an array with 1 object in it, but I can do with it.) }); }, findCurrentTest: function (metaCode, langCode) { Meta.findByCode(metaCode).populate('metaLangs').exec(function(err, metaLang) { console.log('findCurrentTest'); if (err) return console.log(err); console.log(metaLang); // I get what I expected (though not what I want): my meta + all metaLangs related to meta with code "default". // What I want is to get ONE metaLang related to meta with code "default" AND lang with code "en". }); }, findCurrentOthertest: function (metaCode, langCode) { MetaLang.find().populate('meta', {where: {code:metaCode}}).populate('lang', {where: {code:langCode}}).exec(function(err, metaLang) { console.log('findCurrentOthertest'); if (err) return console.log(err); console.log(metaLang); // Doesn't work as I wanted: it gets ALL the metaLang rows. }); } }; 

我也试着首先得到我的元代码,然后我的郎代码,和MetaLang使用Meta.id和Lang.id。 但是,如果我只有一个,我想避免3个查询。

我正在寻找的东西就像MetaLang.find({meta.code:"default", lang.code:"en"})

希望你有所有需要的细节,只是评论,并要求更多,如果你不。

你知道填充是什么吗? 它从数据库加载时包含整个关联的对象。 它实际上是你试图做的连接,如果你所需要的只是行检索而不是查询表而不填充将使你build立的两个函数的工作。

对我来说,看起来你正在重写Sails做这个协会的方式。 Idbuild议给协会文档另一个阅读Sails文档:协会 。 根据你的情况,你只是试图与每个表进行一对多的关联,在我的猜测中,你可以避免一个中间表,但是要确定更好的id需要理解你的用例。

当我看到mySQL代码时,在我看来,你仍然在考虑MySQL和PHP,它们需要时间来转换:)自己强制连接和中间表,重做了很多东西为你自动启动。 我重做你的例子'磁盘'适配器,它的工作完美。 除非绝对必要,否则WaterlineORM的全部内容就是抽象层的SQL。
这里是我会为你的例子,首先没有SQL只是在一个磁盘适配器ID创build模型:

  // Lang.js attributes: { id :{ type: "Integer" , autoIncrement : true, primaryKey: true }, code :"string" } 

你看我在这里做了多less? 我没有真正需要Id部分,因为Sails为我做了。 只是一个例子。

  // Meta.js attributes: { code :"string" } 

更好的:)?

  // MetaLang.js attributes: { title : "string", desc : "string", meta_id : { model : "meta", }, lang_id : { model : "lang", } } 

现在,简单地创build与你的例子相同的值我运行帆控制台types:

  MetaLang.find({meta_id : 1 ,lang_id:2}).exec(function(er,res){ console.log(res); }); 

输出>>>

 sails> [ { meta_id: 1, lang_id: 2, title: 'My blog', id: 2 } ] 

现在,如果要显示id为1的meta和id为2的lang,我们使用populate,但join / search的引用就像这样简单。

 sails> Meta_lang.find({meta_id : 1 ,lang_id:2}).populate('lang_id').populate('meta_id').exec(function(er,res){ console.log(res); }); undefined sails> [ { meta_id: { code: 'default', id: 1 }, lang_id: { code: 'En', id: 2 }, title: 'My blog', id: 2 } ] 

此时,将适配器切换到MySQL, 然后使用与上面相同的列名创buildMySQL表。 创buildFK_constraints和瞧。
您可以添加的另一个严格的政策是设置每个模型的“通过”和优势。 你可以在协会的文档中阅读更多的内容,这取决于协会的性质(多对多等)

为了在不知情的情况下得到相同的结果:

 sails> Meta.findOne({code : "default"}).exec(function(err,needed_meta){ ..... Lang.findOne({code : "En"}).exec(function(err_lang,needed_lang){ ....... Meta_lang.find({meta_id : needed_meta.id , lang_id : needed_lang.id}).exec(function(err_all,result){ ......... console.log(result);}); ....... }); ..... }); undefined sails> [ { meta_id: 1, lang_id: 2, title: 'My blog', id: 2 } ] 

你有没有尝试过:

 findCurrentTest: function (metaCode, langCode) { Meta.findByCode(metaCode).populate('metaLangs', {where: {code:langCode}}).exec(function(err, metaLang) { console.log('findCurrentTest'); if (err) return console.log(err); console.log(metaLang); }); },