Sequelize - включить таблицу через другую таблицу - PullRequest
0 голосов
/ 08 апреля 2020

Учитывая таблицы Project, ProjectVersion, ProjectVersionOverview и следующие ассоциации:

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

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

, поэтому в основном Project -> имеет много ProjectVersion -> имеет много ProjectVersionOverview

ProjectVersion имеет поле ' версия ', которая является возрастающим целым числом, ProjectVersionOverview имеет поле' text ', которое является строкой.

Учитывая идентификатор проекта, я хотел бы вернуть следующее;

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

Что я происходит, если ProjectVersionOverview будет выбираться на основе записи последней версии в ProjectVersion, действуя как объект подразумеваемого объекта и не включается в выходные данные.

Запрос, который я ищу, выглядит примерно так;

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

Я понимаю, что это не правильное использование слова "через", однако, как пример, я думаю, что это имеет смысл.

1 Ответ

0 голосов
/ 13 апреля 2020

Вы должны использовать вложенные include параметры, вот рабочий пример:

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();
  }
})();

Результаты выполнения:

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' }

проверьте базу данных:

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)

Версии зависимостей: "sequelize": "^5.21.3", postgres:9.6

исходный код: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/61109003

...