我想要 Sequelize 形式的这个查询

Posted

技术标签:

【中文标题】我想要 Sequelize 形式的这个查询【英文标题】:I want this query in Sequelize form 【发布时间】:2020-04-05 18:29:25 【问题描述】:

我在 RAW SQL 中获取输出,但无法使用 SequelizeJS

SELECT * FROM `tbl_a` a 
LEFT JOIN `tbl_b` b on b.b_uuid = a.a_uuid
LEFT JOIN `tbl_c` c on c.c_uuid = a.a_uuid

【问题讨论】:

【参考方案1】:

我假设这些表的关系是这样的:

tbl_atbl_b:一对一的关系 tbl_atbl_c:一对一关系

续集版本:"sequelize": "^5.21.3"

/* eslint-disable @typescript-eslint/camelcase */
import  sequelize  from '../../db';
import  Model, DataTypes  from 'sequelize';

class TblA extends Model 
TblA.init(
  
    a_uuid: 
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
      primaryKey: true,
    ,
  ,
   sequelize, modelName: 'tbl_a' ,
);

class TblB extends Model 
TblB.init(
  
    b_uuid: 
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
    ,
  ,
   sequelize, modelName: 'tbl_b' ,
);

class TblC extends Model 
TblC.init(
  
    c_uuid: 
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
    ,
  ,
   sequelize, modelName: 'tbl_c' ,
);

TblA.hasOne(TblB,  foreignKey: 'b_uuid', sourceKey: 'a_uuid', as: 'b' );
TblB.belongsTo(TblA,  foreignKey: 'b_uuid', targetKey: 'a_uuid' );

TblA.hasOne(TblC,  foreignKey: 'c_uuid', sourceKey: 'a_uuid', as: 'c' );
TblC.belongsTo(TblA,  foreignKey: 'c_uuid', targetKey: 'a_uuid' );

(async function test() 
  try 
    await sequelize.sync( force: true );
    // seed
    await TblA.create(
      
        b: ,
        c: ,
      ,
      
        include: [
           model: TblB, as: 'b' ,
           model: TblC, as: 'c' ,
        ],
      ,
    );

    // test
    const result = await TblA.findAll(
      include: [
         model: TblB, as: 'b', required: false ,
         model: TblC, as: 'c', required: false ,
      ],
      raw: true,
    );
    console.log(result);
   catch (error) 
    console.log(error);
   finally 
    await sequelize.close();
  
)();

执行结果:

Executing (default): DROP TABLE IF EXISTS "tbl_c" CASCADE;
Executing (default): DROP TABLE IF EXISTS "tbl_b" CASCADE;
Executing (default): DROP TABLE IF EXISTS "tbl_a" CASCADE;
Executing (default): DROP TABLE IF EXISTS "tbl_a" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "tbl_a" ("a_uuid" UUID , PRIMARY KEY ("a_uuid"));
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 = 'tbl_a' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "tbl_b" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "tbl_b" ("id"   SERIAL , "b_uuid" UUID REFERENCES "tbl_a" ("a_uuid") ON DELETE CASCADE 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 = 'tbl_b' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "tbl_c" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "tbl_c" ("id"   SERIAL , "c_uuid" UUID REFERENCES "tbl_a" ("a_uuid") ON DELETE CASCADE 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 = 'tbl_c' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "tbl_a" ("a_uuid") VALUES ($1) RETURNING *;
Executing (default): INSERT INTO "tbl_b" ("id","b_uuid") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "tbl_c" ("id","c_uuid") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): SELECT "tbl_a"."a_uuid", "b"."id" AS "b.id", "b"."b_uuid" AS "b.b_uuid", "c"."id" AS "c.id", "c"."c_uuid" AS "c.c_uuid" FROM "tbl_a" AS "tbl_a" LEFT OUTER JOIN "tbl_b" AS "b" ON "tbl_a"."a_uuid" = "b"."b_uuid" LEFT OUTER JOIN "tbl_c" AS "c" ON "tbl_a"."a_uuid" = "c"."c_uuid";
[  a_uuid: '1c9cf677-baa9-48c8-ac9b-3e617980c046',
    'b.id': 1,
    'b.b_uuid': '1c9cf677-baa9-48c8-ac9b-3e617980c046',
    'c.id': 1,
    'c.c_uuid': '1c9cf677-baa9-48c8-ac9b-3e617980c046'  ]

sequelize生成的SQL是:

SELECT 
  "tbl_a"."a_uuid", 
  "b"."id" AS "b.id", 
  "b"."b_uuid" AS "b.b_uuid", 
  "c"."id" AS "c.id", 
  "c"."c_uuid" AS "c.c_uuid" 
FROM "tbl_a" AS "tbl_a" 
LEFT OUTER JOIN "tbl_b" AS "b" ON "tbl_a"."a_uuid" = "b"."b_uuid" 
LEFT OUTER JOIN "tbl_c" AS "c" ON "tbl_a"."a_uuid" = "c"."c_uuid";

数据库中的数据记录:

node-sequelize-examples=# select * from tbl_a;
                a_uuid
--------------------------------------
 9d982af2-0ee6-407e-93ee-d9d404178756
(1 row)

node-sequelize-examples=# select * from tbl_b;
 id |                b_uuid
----+--------------------------------------
  1 | 9d982af2-0ee6-407e-93ee-d9d404178756
(1 row)

node-sequelize-examples=# select * from tbl_c;
 id |                c_uuid
----+--------------------------------------
  1 | 9d982af2-0ee6-407e-93ee-d9d404178756
(1 row)

【讨论】:

以上是关于我想要 Sequelize 形式的这个查询的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 sequelize 基于 sqlite3 中的“日期”列进行查询?

了解 Sequelize 中的关联

如何将查询逻辑添加到基于 graphql-sequelize 的设置?

kenx JS 和 Sequelize 有啥区别?

使用 Sequelize.js 进入包含模型

在 Sequelize 中创建对象字段