sequelize association test

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2021-05-29 01:00:00 +00:00
parent c6bf5d990d
commit 6e15ee4b3c
2 changed files with 94 additions and 1 deletions

View File

@@ -0,0 +1,92 @@
#!/usr/bin/env node
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
const Comment = sequelize.define('Comment', {
body: { type: DataTypes.STRING },
}, {});
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
}, {});
User.hasMany(Comment)
Comment.belongsTo(User)
await sequelize.sync({force: true});
const u0 = await User.create({name: 'u0'})
const u1 = await User.create({name: 'u1'})
await Comment.create({body: 'u0c0', UserId: u0.id});
await Comment.create({body: 'u0c1', UserId: u0.id});
await Comment.create({body: 'u1c0', UserId: u1.id});
// Direct way.
{
const u0Comments = await Comment.findAll({
where: { UserId: u0.id },
order: [['id', 'ASC']],
});
assert(u0Comments[0].body === 'u0c0');
assert(u0Comments[1].body === 'u0c1');
assert(u0Comments[0].UserId === u0.id);
assert(u0Comments[1].UserId === u0.id);
// Not added as an object by default. Would require extra query.
assert(u0Comments[0].User === undefined);
assert(u0Comments[1].User === undefined);
}
// Include data from the other side of the association in the query.
{
const u0Comments = await Comment.findAll({
where: { UserId: u0.id },
order: [['id', 'ASC']],
include: [{ model: User }],
});
assert(u0Comments[0].body === 'u0c0');
assert(u0Comments[1].body === 'u0c1');
assert(u0Comments[0].UserId === u0.id);
assert(u0Comments[1].UserId === u0.id);
// These did get added now.
assert(u0Comments[0].User.name === 'u0');
assert(u0Comments[1].User.name === 'u0');
}
// Nicer higher level way.
{
const u0Comments = await u0.getComments({
include: [{ model: User }],
});
assert(u0Comments[0].body === 'u0c0');
assert(u0Comments[1].body === 'u0c1');
assert(u0Comments[0].User.name === 'u0');
assert(u0Comments[1].User.name === 'u0');
}
// No way to create new item with association without explicit foreign key??
// https://stackoverflow.com/questions/34059081/how-do-i-reference-an-association-when-creating-a-row-in-sequelize-without-assum
// This does not work as we would like:
{
await Comment.create({body: 'u0c2', User: u0});
// We'd want 3 here.
assert((await Comment.findAll({
where: { UserId: u0.id },
})).length === 2);
}
// Removal auto-cascades.
const u0id = u0.id
await u0.destroy()
assert((await Comment.findAll({
where: { UserId: u0id },
})).length === 0);
assert((await Comment.findAll({
where: { UserId: u1.id },
})).length === 1);
await sequelize.close();
})();

View File

@@ -0,0 +1,132 @@
#!/usr/bin/env node
// https://cirosantilli.com/sequelize
//
// Before running this:
// * ensure that you can use peer authentication without password
// from the command line, i.e. `psql` works
// * create the database for our test:
// ``
// createdb lkmc-nodejs
// ``
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
// To use the URI syntax, we need an explcit username and password.
// But the second constructor works with peer authentication.
// https://stackoverflow.com/questions/46207155/sequelize-and-peer-authentication-for-postgres
//
// Fails
//const sequelize = new Sequelize('postgres://user:password@localhost:5432/lkmc-nodejs')
//
// Works with peer authentication:
//const sequelize = new Sequelize('lkmc-nodejs', undefined, undefined, {
// host: '/var/run/postgresql',
// dialect: 'postgres',
// logging: false,
//});
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
// OMG fuck this asynchronous bullshit:
// https://stackoverflow.com/questions/39928452/execute-sequelize-queries-synchronously/43250120
(async () => {
// Connection sanity check.
// https://stackoverflow.com/questions/19429152/check-mysql-connection-in-sequelize/31115934
await sequelize.authenticate();
const IntegerNames = sequelize.define('IntegerNames', {
value: {
type: DataTypes.INTEGER,
allowNull: false
},
name: {
type: DataTypes.STRING,
},
}, {});
// Create the database defined by `sequelize.define`.
await IntegerNames.sync({force: true})
// After this:
//
// psql lkmc-nodejs -c '\dt'
//
// gives:
//
// List of relations
// Schema | Name | Type | Owner
// --------+--------------+-------+-------
// public | IntegerNames | table | ciro
// (2 rows)
//
// and:
//
// psql lkmc-nodejs -c '\d+ "IntegerNames"'
//
// gives:
//
// Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
// -----------+--------------------------+-----------+----------+--------------------------------------------+----------+--------------+-------------
// id | integer | | not null | nextval('"IntegerNames_id_seq"'::regclass) | plain | |
// value | integer | | not null | | plain | |
// name | character varying(255) | | | | extended | |
// createdAt | timestamp with time zone | | not null | | plain | |
// updatedAt | timestamp with time zone | | not null | | plain | |
// Indexes:
// "IntegerNames_pkey" PRIMARY KEY, btree (id)
await IntegerNames.create({value: 2, name: 'two'});
await IntegerNames.create({value: 3, name: 'three'});
await IntegerNames.create({value: 5, name: 'five'});
// psql lkmc-nodejs -c 'SELECT * FROM "IntegerNames";'
//
// gives:
//
// id | value | name | createdAt | updatedAt
// ----+-------+-------+----------------------------+----------------------------
// 1 | 2 | two | 2021-03-19 19:12:08.436+00 | 2021-03-19 19:12:08.436+00
// 2 | 3 | three | 2021-03-19 19:12:08.436+00 | 2021-03-19 19:12:08.436+00
// 3 | 5 | five | 2021-03-19 19:12:08.437+00 | 2021-03-19 19:12:08.437+00
// (3 rows)
let integerNames = await IntegerNames.findAll({
where: {
value: 2
}
});
assert(integerNames[0].name === 'two');
// Truncate all tables.
// https://stackoverflow.com/questions/47816162/wipe-all-tables-in-a-schema-sequelize-nodejs/66985334#66985334
await sequelize.truncate();
assert((await IntegerNames.findAll()).length === 0);
// Datetime. Automatically converts to/from date objects.
const Dates = sequelize.define('Dates', {
date: {
type: DataTypes.DATE,
},
}, {});
await Dates.sync({force: true})
let dateCreate = await Dates.create({date: new Date(2000, 0, 1, 2, 3, 4, 5)});
await Dates.create({date: new Date(2000, 0, 1, 2, 3, 4, 6)});
await Dates.create({date: new Date(2000, 0, 1, 2, 3, 4, 7)});
let date = await Dates.findOne({
order: [
['date', 'ASC'],
],
});
assert(date.date.getTime() === new Date(2000, 0, 1, 2, 3, 4, 5).getTime());
assert(date.date.getTime() === dateCreate.date.getTime());
// Otherwise it hangs for 10 seconds, it seems that it keeps the connection alive.
// https://stackoverflow.com/questions/28253831/recreating-database-sequelizejs-is-slow
// https://github.com/sequelize/sequelize/issues/8468
await sequelize.close();
})();