书架查询使用 where 条件连接多个表
Bookshelf query joining mulitiple tables with where criteria
我的一般性问题是,如果您有类似 A(1) -> B(many) -> C(many) -> D(many) 的数据模型,并且您想取出 D 的对象,但是您只有A的标准,怎么办?
这里的细节:
const Contact = bookshelf.Model.extend({
sites: function () {
return this.hasMany(Site);
},
});
const Contacts = bookshelf.Collection.extend({
model: Contact,
});
const Site = bookshelf.Model.extend({
siteAttendances: function () {
return this.hasMany(SiteAttendance);
},
siteSupervisor: function () {
return this.belongsTo(Contact);
},
});
const Sites = bookshelf.Collection.extend({
model: Site,
});
const SiteAttendance = bookshelf.Model.extend({
site: function () {
return this.belongsTo(Site);
},
incidents: function () {
return this.hasMany(Incident);
},
});
const SiteAttendances = bookshelf.Collection.extend({
model: SiteAttendance,
});
const Incident = bookshelf.Model.extend({
siteAttendance: function () {
return this.belongsTo(SiteAttendance);
}
});
const Incidents = bookshelf.Collection.extend({
model: Incident,
});
我有一个联系人 ID(A 对象),但我想要的对象是事件(D 对象),我想知道我是否可以仅使用 bookshelf.js 来做到这一点?使事情复杂化的是,对于每个联系人,都有许多站点和站点出席,但只有少数事件。一个 Contact ID 会产生许多站点,因此可能有一种方法可以使用 through
从事件到站点,但我无法让它工作。我不认为从 Contact 开始并一直执行 withRelated
是正确的方法(因为有太多的 Site 和 SiteAttendance),但我可能是错的。
很遗憾,您不能使用 through
建立深厚的关系。 withRelated
选项将进行 3 次查询以取回联系人的 incidents
。
如果你不介意,withRelated: "sites.siteAttendances.incidents"
会救你。
我遇到了完全相同的问题,我也想知道是否有一些 "Bookshelf-y" 方法可以解决这个问题。我已经实现了一些基于 knex 的代码并且它可以工作。也就是说,它输出带有给定连接的单个 SELECT 语句。
它翻译成你的例子大致如下:
const exampleVal = Incident.forge();
const toSiteAt = exampleVal.siteAttendance();
const incTable = toSiteAt.relatedData.parentTableName;
const saTable = toSiteAt.relatedData.targetTableName;
const saKey = toSiteAt.relatedData.targetIdAttribute;
const forKeySA = toSiteAt.relatedData.foreignKey;
const toSite = toSiteAt.site();
const siteTable = toSite.relatedData.targetTableName;
const siteKey = toSite.relatedData.targetIdAttribute;
const forKeyS = toSite.relatedData.foreignKey;
const toContact = toSite.siteSupervisor();
const contctTable = toContact.relatedData.targetTableName;
const contctKey = toContact.relatedData.targetIdAttribute;
const forKeyC = toContact.relatedData.foreignKey;
return Incident.query( qb => {
qb.innerJoin(saTable, `${incTable}.${forKeySA}`, `${saTable}.${saKey}`)
.innerJoin(siteTable, `${saTable}.${forKeyS}`, `${siteTable}.${siteKey}`)
.innerJoin(contctTable, `${siteTable}.${forKeyC}`, `${contctTable}.${contctKey}`)
.whereIn(`${contctTable}.id`, myContactId); // <1>
}).fetchAll();
<1> 这是您的联系 ID
其他人的问题:实际上还有更多"Bookshelf-y"方法来解决这个问题吗?
我的一般性问题是,如果您有类似 A(1) -> B(many) -> C(many) -> D(many) 的数据模型,并且您想取出 D 的对象,但是您只有A的标准,怎么办?
这里的细节:
const Contact = bookshelf.Model.extend({
sites: function () {
return this.hasMany(Site);
},
});
const Contacts = bookshelf.Collection.extend({
model: Contact,
});
const Site = bookshelf.Model.extend({
siteAttendances: function () {
return this.hasMany(SiteAttendance);
},
siteSupervisor: function () {
return this.belongsTo(Contact);
},
});
const Sites = bookshelf.Collection.extend({
model: Site,
});
const SiteAttendance = bookshelf.Model.extend({
site: function () {
return this.belongsTo(Site);
},
incidents: function () {
return this.hasMany(Incident);
},
});
const SiteAttendances = bookshelf.Collection.extend({
model: SiteAttendance,
});
const Incident = bookshelf.Model.extend({
siteAttendance: function () {
return this.belongsTo(SiteAttendance);
}
});
const Incidents = bookshelf.Collection.extend({
model: Incident,
});
我有一个联系人 ID(A 对象),但我想要的对象是事件(D 对象),我想知道我是否可以仅使用 bookshelf.js 来做到这一点?使事情复杂化的是,对于每个联系人,都有许多站点和站点出席,但只有少数事件。一个 Contact ID 会产生许多站点,因此可能有一种方法可以使用 through
从事件到站点,但我无法让它工作。我不认为从 Contact 开始并一直执行 withRelated
是正确的方法(因为有太多的 Site 和 SiteAttendance),但我可能是错的。
很遗憾,您不能使用 through
建立深厚的关系。 withRelated
选项将进行 3 次查询以取回联系人的 incidents
。
如果你不介意,withRelated: "sites.siteAttendances.incidents"
会救你。
我遇到了完全相同的问题,我也想知道是否有一些 "Bookshelf-y" 方法可以解决这个问题。我已经实现了一些基于 knex 的代码并且它可以工作。也就是说,它输出带有给定连接的单个 SELECT 语句。
它翻译成你的例子大致如下:
const exampleVal = Incident.forge();
const toSiteAt = exampleVal.siteAttendance();
const incTable = toSiteAt.relatedData.parentTableName;
const saTable = toSiteAt.relatedData.targetTableName;
const saKey = toSiteAt.relatedData.targetIdAttribute;
const forKeySA = toSiteAt.relatedData.foreignKey;
const toSite = toSiteAt.site();
const siteTable = toSite.relatedData.targetTableName;
const siteKey = toSite.relatedData.targetIdAttribute;
const forKeyS = toSite.relatedData.foreignKey;
const toContact = toSite.siteSupervisor();
const contctTable = toContact.relatedData.targetTableName;
const contctKey = toContact.relatedData.targetIdAttribute;
const forKeyC = toContact.relatedData.foreignKey;
return Incident.query( qb => {
qb.innerJoin(saTable, `${incTable}.${forKeySA}`, `${saTable}.${saKey}`)
.innerJoin(siteTable, `${saTable}.${forKeyS}`, `${siteTable}.${siteKey}`)
.innerJoin(contctTable, `${siteTable}.${forKeyC}`, `${contctTable}.${contctKey}`)
.whereIn(`${contctTable}.id`, myContactId); // <1>
}).fetchAll();
<1> 这是您的联系 ID
其他人的问题:实际上还有更多"Bookshelf-y"方法来解决这个问题吗?