简体   繁体   English

Sequelize - 通过另一个表包含表

[英]Sequelize - include table through another table

Given the tables Project, ProjectVersion, ProjectVersionOverview, and the following associations;给定表 Project、ProjectVersion、ProjectVersionOverview 和以下关联;

Project.hasMany(ProjectVersion);
ProjectVersion.belongsTo(Project);

ProjectVersion.hasMany(ProjectVersionOverview);
ProjectVersionOverview.belongsTo(ProjectVersion);

so basically Project -> has many ProjectVersion -> has many ProjectVersionOverview所以基本上 Project -> 有很多 ProjectVersion -> 有很多 ProjectVersionOverview

ProjectVersion has the field 'version' which is an incrementing integer, ProjectVersionOverview has the field 'text' which is a string. ProjectVersion 具有字段“版本”,它是一个递增的 integer,ProjectVersionOverview 具有字段“文本”,它是一个字符串。

Given the projectId, I would like to return the following;给定projectId,我想返回以下内容;

result: {
   "projectId": 1,
   "projectVersionOverviews": [
        { "text": ... },
        { "text": ... },
   ]
}

What I am going for is ProjectVersionOverview would be fetched based on the latest version record in ProjectVersion, acting as more of an implied object and not included in the output.我想要的是 ProjectVersionOverview 将根据 ProjectVersion 中的最新版本记录获取,更多地充当隐含的 object 并且不包含在 output 中。

The query I am looking for is something like this;我正在寻找的查询是这样的;

Project.findOne({
    where: { id: projectId },
    include: {
        model: ProjectVersionOverview,
        through: {
            model: ProjectVersion,
            order: [[ "version", "DESC" ]],
            limit: 1
        }
    }
})

I understand this is not the correct usage of 'through', however as an example I think it makes sense.我知道这不是“通过”的正确用法,但是作为一个例子,我认为这是有道理的。

You should use nested include options, here is a working example:您应该使用嵌套include选项,这是一个工作示例:

index.ts : index.ts

import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';

class Project extends Model {}
Project.init({}, { sequelize, modelName: 'projects' });

class ProjectVersion extends Model {}
ProjectVersion.init(
  {
    version: {
      primaryKey: true,
      autoIncrement: true,
      type: DataTypes.INTEGER,
      allowNull: false,
    },
  },
  { sequelize, modelName: 'project_versions' },
);

class ProjectVersionOverview extends Model {}
ProjectVersionOverview.init({ text: DataTypes.STRING }, { sequelize, modelName: 'project_version_overviews' });

Project.hasMany(ProjectVersion);
ProjectVersion.belongsTo(Project);

ProjectVersion.hasMany(ProjectVersionOverview);
ProjectVersionOverview.belongsTo(ProjectVersion);

(async function test() {
  try {
    // create tables
    await sequelize.sync({ force: true });
    // seed
    await Project.create(
      {
        project_versions: [
          {
            project_version_overviews: [{ text: 'a' }, { text: 'b' }],
          },
          {
            project_version_overviews: [{ text: 'x' }, { text: 'y' }, { text: 'z' }],
          },
        ],
      },
      { include: [{ model: ProjectVersion, include: [ProjectVersionOverview] }] },
    );
    // test
    const result = await Project.findOne({
      where: { id: 1 },
      include: [
        {
          model: ProjectVersion,
          attributes: ['version'],
          include: [
            {
              model: ProjectVersionOverview,
              attributes: ['text'],
            },
          ],
        },
      ],
      raw: true,
    });
    console.log(result);
  } catch (error) {
    console.log(error);
  } finally {
    await sequelize.close();
  }
})();

The execution results:执行结果:

Executing (default): DROP TABLE IF EXISTS "project_version_overviews" CASCADE;
Executing (default): DROP TABLE IF EXISTS "project_versions" CASCADE;
Executing (default): DROP TABLE IF EXISTS "projects" CASCADE;
Executing (default): DROP TABLE IF EXISTS "projects" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "projects" ("id"   SERIAL , PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'projects' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "project_versions" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "project_versions" ("version"   SERIAL , "projectId" INTEGER REFERENCES "projects" ("id") ON DELETE SET NULL ON UPDATE CASCADE, PRIMARY KEY ("version"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'project_versions' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "project_version_overviews" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "project_version_overviews" ("id"   SERIAL , "text" VARCHAR(255), "projectVersionVersion" INTEGER REFERENCES "project_versions" ("version") ON DELETE SET NULL ON UPDATE CASCADE, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'project_version_overviews' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "projects" ("id") VALUES (DEFAULT) RETURNING *;
Executing (default): INSERT INTO "project_versions" ("version","projectId") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "project_versions" ("version","projectId") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "project_version_overviews" ("id","text","projectVersionVersion") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): INSERT INTO "project_version_overviews" ("id","text","projectVersionVersion") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): INSERT INTO "project_version_overviews" ("id","text","projectVersionVersion") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): INSERT INTO "project_version_overviews" ("id","text","projectVersionVersion") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): INSERT INTO "project_version_overviews" ("id","text","projectVersionVersion") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): SELECT "projects"."id", "project_versions"."version" AS "project_versions.version", "project_versions->project_version_overviews"."id" AS "project_versions.project_version_overviews.id", "project_versions->project_version_overviews"."text" AS "project_versions.project_version_overviews.text" FROM "projects" AS "projects" LEFT OUTER JOIN "project_versions" AS "project_versions" ON "projects"."id" = "project_versions"."projectId" LEFT OUTER JOIN "project_version_overviews" AS "project_versions->project_version_overviews" ON "project_versions"."version" = "project_versions->project_version_overviews"."projectVersionVersion" WHERE "projects"."id" = 1;
{ id: 1,
  'project_versions.version': 1,
  'project_versions.project_version_overviews.id': 1,
  'project_versions.project_version_overviews.text': 'a' }

check the database:检查数据库:

node-sequelize-examples=# select * from "projects";
 id
----
  1
(1 row)

node-sequelize-examples=# select * from "project_versions";
 version | projectId
---------+-----------
       1 |         1
       2 |         1
(2 rows)

node-sequelize-examples=# select * from "project_version_overviews";
 id | text | projectVersionVersion
----+------+-----------------------
  1 | a    |                     1
  2 | b    |                     1
  3 | x    |                     2
  4 | y    |                     2
  5 | z    |                     2
(5 rows)

Dependencies versions: "sequelize": "^5.21.3" , postgres:9.6依赖版本: "sequelize": "^5.21.3" , postgres:9.6

source code: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/61109003源代码: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/61109003

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM