首页 > 解决方案 > 在 knex.js / Bookshelf.js 中构建复合内连接

问题描述

我正在使用一个数据库架构,其中同一存储库的项目(我们称之为“项目”)通过 bookshelf.jsbelongsToMany关系在链接表中链接,即模型Item与自身具有以下关系:

  items() {
    return this.belongsToMany(Item, 'items_items', 'source', 'target');
  }

现在,简单的部分是链接:

const attachToItems = async (itemIds, options) =>
  Item.items().attach(itemIds, { ...options });

如果要将两个项目(项目 2 和项目 3)附加到项目 1,则使用 2 个条目填充链接表:

| source  | target  |
---------------------
| item1id | item2id | 
| item1id | item3id | 

显然,这个动作也应该暗示 item2 链接到 item 1,因此当您获取 item2(及其相关项目)时,您应该取回 item1。

我试图找出一种方法来组装 knex 查询来做到这一点。

通常withRelated: ['items']fetching 时item1,会生成以下 SQL 查询:

 'select distinct "items".*, "items_items"."source" as "_pivot_source", "items_items"."target" as "_pivot_target" from "items" inner join "items_items" on "items_items"."target" = "items"."id" where "items_items"."source" in (?)'

如果我正在查询“源”项目,即生成链接的项目,这正是我所需要的。

为了以相反的方式获取信息,在 SQL 中,您必须执行以下查询:

select distinct "items".*, "items_items"."source" as "_pivot_source", "items_items"."target" as "_pivot_target" from "items" inner join "items_items" on "items_items"."source" = "items"."id" or "items_items"."target" = "items"."id" where "items"."id" <> $' and ("items_items"."source" = $ or "items_items"."target" = $)

其中,为方便起见,$代表您要获取的项目的 id。

现在,除了 bookshelf.js,我们还使用 knex.js,我知道您可以扩展查询构建器,例如,编写:

 withRelated: [
          {
            items: (qb) =>
              console.log(
                qb.toSQL(),
              ),
          },
        ],

上面的代码显示了以下 SQL 查询:

select * from "items" inner join "items_items" on "items_items"."target" = "items"."id"

正如您所看到的,它已经在我们可以干预和构建查询的最早阶段,与我们需要的略有不同(即不仅是“目标”,还有“源”)。

有没有办法在早期阶段拦截和扩展这个流程,利用 bookshelf 的belongsToMany方法的力量,从而直接查询 Item 存储库并使用(with)相关流程?如果是这样,该方法链会是什么样子?

手指交叉以获得积极的回应;)

热情地

标签: postgresqlknex.jsbookshelf.js

解决方案


推荐阅读