методы sequelize из ассоциации fooInstance.getBars (), возвращающие неверное значение - PullRequest
0 голосов
/ 23 марта 2020

У меня есть 2 модели с ассоциацией «многие ко многим» через другую модель. По умолчанию Sequelize создает методы экземпляров для обеих моделей, как вы все знаете (https://sequelize.org/master/manual/assocs.html#special -methods-mixins-добавлен-в-экземплярах ).

Моя проблема заключается в том, что оба метода fooInstance.getBars () и fooInstance.countBars () возвращают неверное количество записей.

База данных была настроена с использованием файлов миграции с разделителями.

Ниже представлены 3 модели.

module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define(
    "User",
    {
      firstName: DataTypes.STRING
    },
    {}
  );
  User.associate = function(models) {
    // associations can be defined here
    User.belongsToMany(models.Week, {
      through: models.Roster,
      foreignKey: {
        name: "weekId"
      }
    });
  };
  return User;
};

"use strict";
module.exports = (sequelize, DataTypes) => {
  const Week = sequelize.define(
    "Week",
    {
      date: {
        type: DataTypes.DATE,
        allowNull: false,
        unique: true
      }
    },
    {}
  );
  Week.associate = function(models) {
    // associations can be defined here
    Week.belongsToMany(models.User, {
      through: models.Roster,
      foreignKey: {
        name: "userId",
        allowNull: true
      }
    });
  };
  return Week;
};

"use strict";
module.exports = (sequelize, DataTypes) => {
  const Roster = sequelize.define(
    "Roster",
    {
      weekId: {
        type: DataTypes.INTEGER,
        allowNull: false,
        unique: false
      },
      userId: {
        type: DataTypes.INTEGER,
        allowNull: true,
        unique: false
      }
    },
    {}
  );
  Roster.associate = function(models) {
    // associations can be defined here
  };
  return Roster;
};


Прежде чем тестировать методы, я создал 1 запись за недели и 5 записей у пользователей, затем я создал 5 ассоциаций используя 5 Roster.create () в реестрах.

Когда я выполняю запрос в моем файле маршрутов, как этот await Week.getUsers(), вместо того, чтобы возвращать 5 пользователей в массиве, он возвращает 1 в массиве. Точно так же код await Week.countUsers() вернул 1 вместо 5.

Пожалуйста, помогите!

Пожалуйста, дайте мне знать, если я пропустил какую-либо важную информацию.

Спасибо!

1 Ответ

1 голос
/ 14 апреля 2020

Как сказано в документах :

Когда определяется связь между двумя моделями, экземпляры этих моделей получают специальные методы для взаимодействия со связанными с ними аналогами .

Вы пытаетесь вызвать эти специальные методы в классе Model. Вот рабочий пример:

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

class User extends Model {}
User.init(
  {
    firstName: DataTypes.STRING,
  },
  { sequelize, modelName: 'User' },
);

class Week extends Model {
  public getUsers!: BelongsToManyGetAssociationsMixin<User>;
  public countUsers!: BelongsToManyCountAssociationsMixin;
}
Week.init(
  {
    date: {
      type: DataTypes.DATE,
      allowNull: false,
      unique: true,
    },
  },
  { sequelize, modelName: 'Week' },
);

class Roster extends Model {}
Roster.init(
  {
    weekId: {
      type: DataTypes.INTEGER,
      allowNull: false,
      unique: false,
    },
    userId: {
      type: DataTypes.INTEGER,
      allowNull: true,
      unique: false,
    },
  },
  { sequelize, modelName: 'Roster' },
);

User.belongsToMany(Week, { through: Roster, foreignKey: { name: 'weekId' } });
Week.belongsToMany(User, { through: Roster, foreignKey: { name: 'userId', allowNull: true } });

(async function test() {
  try {
    // create tables
    await sequelize.sync({ force: true });
    // seed
    const week = await Week.create(
      {
        date: new Date(),
        Users: [
          { firstName: 'james' },
          { firstName: 'elsa' },
          { firstName: 'tim' },
          { firstName: 'lee' },
          { firstName: 'jasmine' },
        ],
      },
      { include: [User] },
    );
    // test
    const count = await week.countUsers();
    console.log('count:', count);
    const users = await week.getUsers();
    console.log('users count:', users.length);
  } catch (error) {
    console.log(error);
  } finally {
    await sequelize.close();
  }
})();

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

Executing (default): DROP TABLE IF EXISTS "Roster" CASCADE;
Executing (default): DROP TABLE IF EXISTS "Week" CASCADE;
Executing (default): DROP TABLE IF EXISTS "User" CASCADE;
Executing (default): DROP TABLE IF EXISTS "User" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "User" ("id"   SERIAL , "firstName" VARCHAR(255), 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 = 'User' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "Week" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "Week" ("id"   SERIAL , "date" TIMESTAMP WITH TIME ZONE NOT NULL UNIQUE, 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 = 'Week' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "Roster" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "Roster" ("weekId" INTEGER NOT NULL  REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "userId" INTEGER  REFERENCES "Week" ("id") ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE ("weekId", "userId"), PRIMARY KEY ("weekId","userId"));
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 = 'Roster' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "Week" ("id","date") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "User" ("id","firstName") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "User" ("id","firstName") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "User" ("id","firstName") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "User" ("id","firstName") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "User" ("id","firstName") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "Roster" ("weekId","userId") VALUES ($1,$2) RETURNING *;
Executing (default): INSERT INTO "Roster" ("weekId","userId") VALUES ($1,$2) RETURNING *;
Executing (default): INSERT INTO "Roster" ("weekId","userId") VALUES ($1,$2) RETURNING *;
Executing (default): INSERT INTO "Roster" ("weekId","userId") VALUES ($1,$2) RETURNING *;
Executing (default): INSERT INTO "Roster" ("weekId","userId") VALUES ($1,$2) RETURNING *;
Executing (default): SELECT COUNT("User"."id") AS "count" FROM "User" AS "User" INNER JOIN "Roster" AS "Roster" ON "User"."id" = "Roster"."weekId" AND "Roster"."userId" = 1;
count: 5
Executing (default): SELECT "User"."id", "User"."firstName", "Roster"."weekId" AS "Roster.weekId", "Roster"."userId" AS "Roster.userId" FROM "User" AS "User" INNER JOIN "Roster" AS "Roster" ON "User"."id" = "Roster"."weekId" AND "Roster"."userId" = 1;
users count: 5

проверка базы данных:

node-sequelize-examples=# select * from "User";
 id | firstName
----+-----------
  1 | james
  2 | elsa
  3 | tim
  4 | lee
  5 | jasmine
(5 rows)

node-sequelize-examples=# select * from "Week";
 id |           date
----+---------------------------
  1 | 2020-04-14 01:56:56.55+00
(1 row)

node-sequelize-examples=# select * from "Roster";
 weekId | userId
--------+--------
      1 |      1
      2 |      1
      3 |      1
      4 |      1
      5 |      1
(5 rows)

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

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

...