书架查询使用 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"方法来解决这个问题吗?