代码之家  ›  专栏  ›  技术社区  ›  ricka

将多个表与where条件连接起来的Bookshelf查询

  •  1
  • ricka  · 技术社区  · 9 年前

    我的一般问题是,如果您有类似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(a对象),但我想要的对象是Incidents(D对象),我想知道我能用书架来做这件事吗。js?更复杂的是,对于每个联系人,都有许多站点和站点出勤,但只有少数事件。一个联系人ID将产生多个站点,因此可以使用 through ,但我还没能做到。我不认为从接触开始 withRelated 所有的方法都是正确的(因为有很多Site和SiteAttendance),但我可能错了。

    2 回复  |  直到 9 年前
        1
  •  0
  •   absolux    9 年前

    糟糕的是你不能使用 through withRelated 选项,将进行3次查询以取回联系人的 incidents . 如果你不在乎, withRelated: "sites.siteAttendances.incidents" 会救你的。

        2
  •  0
  •   bgerth    9 年前

    我也有同样的问题,我想知道是否有一些“书架式”的方法可以做到这一点。我实现了一些基于knex的代码,它可以工作。也就是说,它输出单个 选择 具有给定联接的语句。

    将其转换为您的示例,大致如下:

      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

    其他人的问题是:真的有更多的“书架y”方法来解决这个问题吗?