书架查询将多个表与标准联系起来

时间:2016-08-05 14:39:28

标签: bookshelf.js knex.js

我的一般性问题是,如果您的数据模型类似于A(1) - > B(很多) - > C(许多) - > D(很多)并且你想要获得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(一个对象),但我想要事件(D对象)的对象,我想知道我可以只用bookshelf.js吗?更复杂的是,对于每个联系人,都有很多站点和SiteAttendances,但只有少数事件。一个联系人ID将产生许多站点,因此可能有一种方法可以使用through从事件到站点执行此操作,但我无法使其工作。我不认为从联系开始并且withRelated一直向下做正确的方法(因为有太多的Site和SiteAttendance),但我可能是错的。

2 个答案:

答案 0 :(得分:0)

严重的是,您不能将through用于深层关系。并且withRelated选项会进行3次查询以获取联系人的incidents。 如果你不在乎,withRelated: "sites.siteAttendances.incidents"会救你。

答案 1 :(得分:0)

我有完全相同的问题,我也想知道是否有一些“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();

&LT 1为卤素;这是您的联系人ID

向其他人提问:实际上还有更多的“Bookshelf-y”解决方法吗?