runoops.com

Sequelize 原始查询

本教程实例代码:https://gitee.com/liqiang88/sequelize-test

本章节需要用到的MySQL 数据,需要执行$ node user_create.js 来创建user 表并添加数据。

由于常常使用简单的方式来执行原始/已经准备好的SQL查询,因此可以使用 sequelize。query 方法。

默认情况下,函数将返回两个参数 - 一个结果数组,以及一个包含元数据(例如受影响的行数等)的对象。 请注意,由于这是一个原始查询,所以元数据都是具体的方言。 某些方言返回元数据 "within" 结果对象(作为数组上的属性)。 但是,将永远返回两个参数,但对于MSSQL和MySQL,它将是对同一对象的两个引用。

const [results, metadata] = await sequelize.query("UPDATE users SET y = 42 WHERE x = 12");
// 结果将是一个空数组,元数据将包含受影响的行数.

在不需要访问元数据的情况下,你可以传递一个查询类型来告诉后续如何格式化结果。 例如,对于一个简单的选择查询你可以做:

user_test2.js:

const {QueryTypes } = require('sequelize');
const SequelizeConn = require('./SequelizeConn');
const UserModel = require('./UserModel');

(async () => {
    // 这里是代码
    const users = await SequelizeConn.query("SELECT * FROM `users`");
    const users = await SequelizeConn.query("SELECT * FROM `users`", { type: QueryTypes.SELECT });
    console.log(users);
})();

执行后的结果:

$ node user_test2.js
Executing (default): SELECT * FROM `users`
[
  {
    id: 1,
    username: 'Runoops',
    password: '202cb962ac59075b964b07152d234b70',
    firstName: 'Marie',
    lastName: 'Cox',
    createdAt: 2023-05-09T07:18:48.000Z,
    updatedAt: 2023-05-09T07:18:48.000Z
  }
]

还有其他几种查询类型可用。 详细了解来源

第二种选择是模型。如果传递模型,返回的数据将是该模型的实例。

user_test2.js:

const {QueryTypes } = require('sequelize');

const SequelizeConn = require('./SequelizeConn');

const UserModel = require('./UserModel');

(async () => {
    // 这里是代码
    // const users = await SequelizeConn.query("SELECT * FROM `users`");
    // const users = await SequelizeConn.query("SELECT * FROM `users`", { type: QueryTypes.SELECT });
    //console.log(users);

    //UserModel 是模型定义。 这样你就可以轻松地将查询映射到预定义的模型
    const users = await SequelizeConn.query("SELECT * FROM `users`", { 
        model: UserModel,
        mapToModel:true  // 如果你有任何映射字段,则在此处传递 true
    });
    // 现在,`users` 的每个元素都是 UserModel 的一个实例
    //转化为数组对象
    const userArr = users.map((item) => {return item.toJSON()});
    console.log(userArr);
})();

执行结果:

$ node user_test2.js
Executing (default): SELECT * FROM `users`
[
  {
    username: 'RUNOOPS',
    fullName: 'Marie Cox',
    id: 1,
    password: '202cb962ac59075b964b07152d234b70',
    firstName: 'Marie',
    lastName: 'Cox',
    createdAt: 2023-05-09T07:18:48.000Z,
    updatedAt: 2023-05-09T07:18:48.000Z
  }
]

查看 Query API 参考中的更多参数。以下是一些例子:

const {QueryTypes } = require('sequelize');

const SequelizeConn = require('./SequelizeConn');

// const UserModel = require('./UserModel');


(async () => {
    await SequelizeConn.query('SELECT 1', {
        // 用于记录查询的函数(或false)
        // 将调用发送到服务器的每个SQL查询.
        logging: console.log,
      
        // 如果plain为true,则sequelize将仅返回结果集的第一条记录. 
        // 如果是false,它将返回所有记录.
        plain: false,
      
        // 如果你没有查询的模型定义,请将此项设置为true.
        raw: false,
      
        // 你正在执行的查询类型. 查询类型会影响结果在传回之前的格式.
        type: QueryTypes.SELECT
      });
      
      // 注意第二个参数为null!
      // 即使我们在这里声明了一个被调用对象,
      // raw: true 也会取代并返回一个原始对象.
      
      console.log(await SequelizeConn.query('SELECT * FROM users', { raw: true }));
})();

nest 参数

如果表的属性名称包含点,则可以通过设置 nest: true 参数将生成的对象变为嵌套对象。这可以通过 dottie.js 在后台实现。见下文:

不使用 nest: true

test_nest.js

const { QueryTypes } = require('sequelize');
const SequelizeConn = require('./SequelizeConn');

(async () => {
    const records = await SequelizeConn.query('select 1 as `foo.bar.baz`', {
        type: QueryTypes.SELECT,
    });
    console.log(JSON.stringify(records[0], null, 2));
})();

执行结果:

$ node test_nest.js
Executing (default): select 1 as `foo.bar.baz`
{
  "foo.bar.baz": 1
}

使用 nest: true

test_nest2.js

const { QueryTypes } = require('sequelize');
const SequelizeConn = require('./SequelizeConn');

(async () => {
    const records = await SequelizeConn.query('select 1 as `foo.bar.baz`', {
        type: QueryTypes.SELECT,
        nest:true
    });
    console.log(JSON.stringify(records[0], null, 2));

})();

执行结果:

$ node test_nest2.js
Executing (default): select 1 as `foo.bar.baz`
{
  "foo": {
    "bar": {
      "baz": 1
    }
  }
}

替换

查询中的替换可以通过两种不同的方式完成:使用命名参数(以:开头),或者由表示的未命名参数。替换在options对象中传递。

  • 如果传递一个数组, ? 将按照它们在数组中出现的顺序被替换
  • 如果传递一个对象, :key 将替换为该对象的键。 如果对象包含在查询中找不到的键,则会抛出异常,反之亦然。
const { QueryTypes } = require('sequelize');
const SequelizeConn = require('./SequelizeConn');

(async () => {
    await SequelizeConn.query(
        'SELECT * FROM users WHERE username = ?',
        {
            replacements: ['Runoops'],
            type: QueryTypes.SELECT
        }
    );

    await SequelizeConn.query(
        'SELECT * FROM users WHERE username = :username',
        {
            replacements: { username: 'Runoops' },
            type: QueryTypes.SELECT
        }
    );

    //数组替换将自动处理,以下查询将搜索用户名与值数组匹配的项目。
    await SequelizeConn.query(
        'SELECT * FROM users WHERE username IN(:username)',
        {
            replacements: { username: ['Runoops', 'Runoops123'] },
            type: QueryTypes.SELECT
        }
    );

    //要使用通配符运算符 %,请将其附加到你的替换中. 以下查询与用户名以 'Run' 开头的用户名相匹配。
    await SequelizeConn.query(
        'SELECT * FROM users WHERE username LIKE :search_name',
        {
            replacements: { search_name: 'Run%' },
            type: QueryTypes.SELECT
        }
    );

})();

绑定参数

绑定参数就像替换。 除非替换被转义并在查询发送到数据库之前通过后续插入到查询中,而将绑定参数发送到SQL查询文本之外的数据库。 查询可以具有绑定参数或替换。绑定参数由 $1, $2, 。。。 (numeric) 或 $key (alpha-numeric) 引用。这是独立于方言的。

如果传递一个数组, $1 被绑定到数组中的第一个元素 (bind[0])。
如果传递一个对象, $key 绑定到 object['key']。 每个键必须以非数字字符开始。 $1 不是一个有效的键,即使 object['1'] 存在。
在这两种情况下 $$ 可以用来转义一个 $ 字符符号。
数组或对象必须包含所有绑定的值,或者Sequelize将抛出异常。 这甚至适用于数据库可能忽略绑定参数的情况。

数据库可能会增加进一步的限制。 绑定参数不能是SQL关键字,也不能是表或列名。 引用的文本或数据也忽略它们。 在PostgreSQL中,如果不能从上下文 $1::varchar 推断类型,那么也可能需要对其进行类型转换。

const { QueryTypes } = require('sequelize');

await sequelize.query(
  'SELECT *, "text with literal $$1 and literal $$status" as t FROM projects WHERE status = $1',
  {
    bind: ['active'],
    type: QueryTypes.SELECT
  }
);

await sequelize.query(
  'SELECT *, "text with literal $$1 and literal $$status" as t FROM projects WHERE status = $status',
  {
    bind: { status: 'active' },
    type: QueryTypes.SELECT
  }
);

Captcha Code

0 笔记

分享笔记

Inline Feedbacks
View all notes