TypeORM Postgres WHERE ANY 或 IN With QueryBuilder or Find?
TypeORM Postgres WHERE ANY or IN With QueryBuilder Or Find?
我一直在试图弄清楚如何 select Postgres 数据库中的每条记录,这些记录在具有整数数组的列中包含某个 id。我是新手,但我相信我想要一个如下所示的 SQL 语句:
SELECT * FROM members WHERE 2 = ANY(skill_id_array);
skill_id_array 列中的数据如下所示:{1,4,7}。
从 Angular 前端我传入一个 id,例如 2 作为参数。登录终端显示 select 语句的结尾,但它失败了:
... WHERE ANY (skill_id_array) -- PARAMETERS: [2]
我认为问题是我试图将一个变量传递到代码中,但它讨厌它。请注意,我一直在尝试查找方法和 QueryBuilder。结果错误在评论中。 (完整的 CRUD 正在运行,所以我的整体设置没问题。)
这很好用,但我知道这有一个 sql 注入问题:
const membersBySkill = await this.entityManager.query(
`SELECT * FROM members WHERE ${integerId} = ANY(members.skill_id_array)`
);
这有效,但我不确定 sql 注入问题,而且我想使用 TypeORM find 或 QueryBuilder。
const sql = 'SELECT * FROM members WHERE '+ integerId + ' = ANY(skill_id_array)';
const membersBySkill = await this.entityManager.query(sql);
为我服务:
import {Any} from "typeorm";
async getMembersBySkill(id) {
const integerId = parseInt(id, 10); // convert id to integer for Postgres array.
// console.log('skill_id in service', integerId);
// Find one skill id in an array of id's.
/*
const membersBySkill = await this.connection.getRepository(Members).find({
skill_id_array: Any(integerId)
});
// This results in an IDE error. It doesn't like a number as
// the ANY param. "{integerId: number} is not assignable to
// parameter type '{}[] | FindOperator<{}>'.
// In terminal: error: could not find array type for data type integer[].
// However, the db has integers.
*/
const membersBySkill = await getRepository(Members)
.createQueryBuilder("members")
.select('*')
.where(":id IN (skill_id_array)", {id: integerId})
.getMany();
// SELECT * FROM "members" "members" WHERE IN (skill_id_array) -- PARAMETERS: [2]
// server console: error: malformed array literal: "2"
console.log('membersBySkill: ', membersBySkill);
return membersBySkill;
}
实体:
@Column('int', { array: true, nullable: true})
skill_id_array: number[];
Postgres 列类型:integer[]
我每次更改都会停止和启动 Nestjs 服务器。
网上很多地方都说SQL运算符IN和ANY几乎是等价的。所以我的方向是认为它们的设置几乎相同,只是 ANY 需要“=”。错了,但花了很长时间才弄明白。
QueryBuilder 中的任何设置都有效:
const membersBySkill = await getRepository(Members)
.createQueryBuilder()
.where(':id = ANY (skill_id_array)', {id: integerId})
.getMany();
之前我使用的是 TypeORM Find Options 文档中的 'Any' 设置,因为 QueryBuilder 文档中(尚未)未解决任何问题。当时这似乎是可行的方法,但不要将它们混在一起。
TypeORM 主要贡献者@pleerock 建议在此设置中使用别名,因此这是他的示例以供参考别名 'member':
const results = await getRepository(Members)
.createQueryBuilder("member") // you shall assign an alias
.where(":id = ANY(member.skill_id_array)", { id: 1 }) // and use that alias everywhere in your query builder
.getMany();
那么 IN 呢?
问题是您不能像在 ANY 中那样在 IN 中使用变量。它永远不会工作。它需要一个 'list of scalars' 而不是文档如何表达的表达式。我的 var 包含一个标量列表,但 IN 参数必须有一个列表,而不是对列表的引用。
IN (id1, id2, id5)
应该可以工作,您需要用整数或字符串在其他地方填充这些变量。对于我的应用程序,这意味着解析我的 skill_id_array 并将各个整数分配给它们自己的唯一变量。当 ANY 可以轻松完成相同的结果时,这是很多工作。
目前可以使用语法
.where("id IN(:...ids)", { ids: [1,2,3] })
如果您使用 OOP
const list = await this.repository.find({ where: { id: In([...idArr]) } });
我一直在试图弄清楚如何 select Postgres 数据库中的每条记录,这些记录在具有整数数组的列中包含某个 id。我是新手,但我相信我想要一个如下所示的 SQL 语句:
SELECT * FROM members WHERE 2 = ANY(skill_id_array);
skill_id_array 列中的数据如下所示:{1,4,7}。
从 Angular 前端我传入一个 id,例如 2 作为参数。登录终端显示 select 语句的结尾,但它失败了:
... WHERE ANY (skill_id_array) -- PARAMETERS: [2]
我认为问题是我试图将一个变量传递到代码中,但它讨厌它。请注意,我一直在尝试查找方法和 QueryBuilder。结果错误在评论中。 (完整的 CRUD 正在运行,所以我的整体设置没问题。)
这很好用,但我知道这有一个 sql 注入问题:
const membersBySkill = await this.entityManager.query(
`SELECT * FROM members WHERE ${integerId} = ANY(members.skill_id_array)`
);
这有效,但我不确定 sql 注入问题,而且我想使用 TypeORM find 或 QueryBuilder。
const sql = 'SELECT * FROM members WHERE '+ integerId + ' = ANY(skill_id_array)';
const membersBySkill = await this.entityManager.query(sql);
为我服务:
import {Any} from "typeorm";
async getMembersBySkill(id) {
const integerId = parseInt(id, 10); // convert id to integer for Postgres array.
// console.log('skill_id in service', integerId);
// Find one skill id in an array of id's.
/*
const membersBySkill = await this.connection.getRepository(Members).find({
skill_id_array: Any(integerId)
});
// This results in an IDE error. It doesn't like a number as
// the ANY param. "{integerId: number} is not assignable to
// parameter type '{}[] | FindOperator<{}>'.
// In terminal: error: could not find array type for data type integer[].
// However, the db has integers.
*/
const membersBySkill = await getRepository(Members)
.createQueryBuilder("members")
.select('*')
.where(":id IN (skill_id_array)", {id: integerId})
.getMany();
// SELECT * FROM "members" "members" WHERE IN (skill_id_array) -- PARAMETERS: [2]
// server console: error: malformed array literal: "2"
console.log('membersBySkill: ', membersBySkill);
return membersBySkill;
}
实体:
@Column('int', { array: true, nullable: true})
skill_id_array: number[];
Postgres 列类型:integer[]
我每次更改都会停止和启动 Nestjs 服务器。
网上很多地方都说SQL运算符IN和ANY几乎是等价的。所以我的方向是认为它们的设置几乎相同,只是 ANY 需要“=”。错了,但花了很长时间才弄明白。
QueryBuilder 中的任何设置都有效:
const membersBySkill = await getRepository(Members)
.createQueryBuilder()
.where(':id = ANY (skill_id_array)', {id: integerId})
.getMany();
之前我使用的是 TypeORM Find Options 文档中的 'Any' 设置,因为 QueryBuilder 文档中(尚未)未解决任何问题。当时这似乎是可行的方法,但不要将它们混在一起。
TypeORM 主要贡献者@pleerock 建议在此设置中使用别名,因此这是他的示例以供参考别名 'member':
const results = await getRepository(Members)
.createQueryBuilder("member") // you shall assign an alias
.where(":id = ANY(member.skill_id_array)", { id: 1 }) // and use that alias everywhere in your query builder
.getMany();
那么 IN 呢?
问题是您不能像在 ANY 中那样在 IN 中使用变量。它永远不会工作。它需要一个 'list of scalars' 而不是文档如何表达的表达式。我的 var 包含一个标量列表,但 IN 参数必须有一个列表,而不是对列表的引用。
IN (id1, id2, id5)
应该可以工作,您需要用整数或字符串在其他地方填充这些变量。对于我的应用程序,这意味着解析我的 skill_id_array 并将各个整数分配给它们自己的唯一变量。当 ANY 可以轻松完成相同的结果时,这是很多工作。
目前可以使用语法
.where("id IN(:...ids)", { ids: [1,2,3] })
如果您使用 OOP
const list = await this.repository.find({ where: { id: In([...idArr]) } });