Tengo 2 modelos, uno se llama Usuario y el segundo Preferencias. Existe una asociación entre ambos:

User.hasOne(Preferences)

Suponiendo que el usuario es una instancia de Usuario y prefiere una de Preferencias y una declaración como:

user.setPreferences(pref)

Luego, el usuario y la preferencia de AFAIU están vinculados de alguna manera (incluso si aún no están almacenados en la base de datos). Entonces, desde la perspectiva del usuario, ¿cómo puedo acceder a sus preferencias asociadas? El uso de getPreferences () llamará a la base de datos, que es inútil en este caso ... He comprobado user.preferences y user._preferences pero ambos no están definidos.

¿Existe una manera fácil de tener un controlador en los elementos asociados?

0
lucas_dev 21 ene. 2021 a las 22:43

1 respuesta

La mejor respuesta

El user.Preferences se completa cuando se solicita explícitamente en un código como este:

const user2: User = await User.findOne({ where: { id: 1 }, include: [Preference] });
console.log(user2.Preferences); // it's only populated when explicitly requested in code

Enviará SQL a la base de datos. De lo contrario, el valor es undefined.

La forma más fácil es crear la propiedad privada en la clase de modelo User y almacenar las instancias del modelo preferences asociadas para cada instancia de usuario después de ejecutar user.setPreferences(pref) con éxito sin llamar a DB.

P.ej. usando "sequelize": "^5.21.3"

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

class User extends Model {
  public id!: number;

  public getPreferences!: HasManyGetAssociationsMixin<Preference>;
  public setPreferences!: HasManySetAssociationsMixin<Preference, Preference['id']>;
  public readonly Preferences?: Preference[];

  public _inMemoryAssociatedPreferences: Preference[] = [];
}
User.init({}, { sequelize });

class Preference extends Model {
  public id!: number;
  public name!: string;
}
Preference.init({ name: DataTypes.STRING }, { sequelize });

User.hasMany(Preference);
Preference.belongsTo(User);

(async function test() {
  await sequelize.sync({ force: true });
  await User.create({ id: 1 });
  const user: User = await User.findOne({ where: { id: 1 } });
  const pref = await Preference.create({ id: 1, name: 'a' });
  await user.setPreferences(pref);
  user._inMemoryAssociatedPreferences = [pref];

  // elsewhere
  console.log('in memory preferences:', user._inMemoryAssociatedPreferences);
  await sequelize.close();
})();

Salida:

Executing (default): DROP TABLE IF EXISTS "Preference" 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 , 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 "Preference" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "Preference" ("id"   SERIAL , "name" VARCHAR(255), "UserId" INTEGER REFERENCES "User" ("id") 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 = 'Preference' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "User" ("id") VALUES ($1) RETURNING *;
Executing (default): SELECT "id" FROM "User" AS "User" WHERE "User"."id" = 1;
Executing (default): INSERT INTO "Preference" ("id","name") VALUES ($1,$2) RETURNING *;
Executing (default): SELECT "id", "name", "UserId" FROM "Preference" AS "Preference" WHERE "Preference"."UserId" = 1;
Executing (default): UPDATE "Preference" SET "UserId"=$1 WHERE "id" IN (1)
in memory preferences: [
  Preference {
    dataValues: { id: 1, name: 'a', UserId: null },
    _previousDataValues: { id: 1, name: 'a', UserId: null },
    _changed: { id: false, name: false, UserId: false },
    _modelOptions: {
      timestamps: false,
      validate: {},
      freezeTableName: true,
      underscored: false,
      paranoid: false,
      rejectOnEmpty: false,
      whereCollection: [Object],
      schema: null,
      schemaDelimiter: '',
      defaultScope: {},
      scopes: {},
      indexes: [],
      name: [Object],
      omitNull: false,
      sequelize: [Sequelize],
      hooks: {}
    },
    _options: {
      isNewRecord: true,
      _schema: null,
      _schemaDelimiter: '',
      attributes: undefined,
      include: undefined,
      raw: undefined,
      silent: undefined
    },
    isNewRecord: false
  }
]
0
slideshowp2 22 ene. 2021 a las 09:17