The user.Preferences
is populated when explicitly requested in code like this:
const user2: User = await User.findOne({ where: { id: 1 }, include: [Preference] });
console.log(user2.Preferences); // it's only populated when explicitly requested in code
It will send SQL to DB. Otherwise, the value is undefined
.
The easiest way is to create the private property on the User
model class and store the associated preferences
model instances for each user instance after executing user.setPreferences(pref)
successfully without calling DB.
E.g. using "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();
})();
Output:
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
}
]