如何在TypeORM服务中对PostgreSQL实体数组字段进行增删改?
TypeORM实体数组字段的增删改操作(PostgreSQL)
假设你的服务层已注入FavoritesEntity的Repository:
import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { FavoritesEntity } from './favorites.entity'; @Injectable() export class FavoritesService { constructor( @InjectRepository(FavoritesEntity) private readonly favoritesRepo: Repository<FavoritesEntity>, ) {} // 以下为各类操作实现 }
1. 向数组字段添加元素
方式一:查询实体后修改保存(直观易读)
适合需要校验重复元素、需读取原数组内容的场景:
async addArtist(favoriteId: number, artistId: string): Promise<FavoritesEntity> { const favorite = await this.favoritesRepo.findOneBy({ id: favoriteId }); if (!favorite) throw new Error('收藏记录不存在'); // 避免重复添加相同ID if (!favorite.artists.includes(artistId)) { favorite.artists.push(artistId); } return this.favoritesRepo.save(favorite); }
方式二:用查询构建器执行PostgreSQL数组函数(高效)
无需查询整个实体,直接通过数据库语句修改,适合批量操作或无需读取原数组的场景:
// 添加单个元素 async addArtist(favoriteId: number, artistId: string): Promise<void> { await this.favoritesRepo .createQueryBuilder() .update(FavoritesEntity) .set({ artists: () => 'array_append(artists, :artistId)' }) .setParameters({ artistId, id: favoriteId }) .where('id = :id') .execute(); } // 批量添加多个元素 async addArtists(favoriteId: number, artistIds: string[]): Promise<void> { await this.favoritesRepo .createQueryBuilder() .update(FavoritesEntity) .set({ artists: () => 'array_cat(artists, :artistIds)' }) .setParameters({ artistIds, id: favoriteId }) .where('id = :id') .execute(); }
2. 从数组字段删除元素
方式一:查询实体后过滤保存
async removeArtist(favoriteId: number, artistId: string): Promise<FavoritesEntity> { const favorite = await this.favoritesRepo.findOneBy({ id: favoriteId }); if (!favorite) throw new Error('收藏记录不存在'); favorite.artists = favorite.artists.filter(id => id !== artistId); return this.favoritesRepo.save(favorite); }
方式二:用PostgreSQL的array_remove函数
async removeArtist(favoriteId: number, artistId: string): Promise<void> { await this.favoritesRepo .createQueryBuilder() .update(FavoritesEntity) .set({ artists: () => 'array_remove(artists, :artistId)' }) .setParameters({ artistId, id: favoriteId }) .where('id = :id') .execute(); }
3. 更新数组字段
替换整个数组
直接用新数组覆盖原数组:
// 查询后保存 async updateArtists(favoriteId: number, newArtistIds: string[]): Promise<FavoritesEntity> { const favorite = await this.favoritesRepo.findOneBy({ id: favoriteId }); if (!favorite) throw new Error('收藏记录不存在'); favorite.artists = newArtistIds; return this.favoritesRepo.save(favorite); } // 直接用查询构建器更新 async updateArtists(favoriteId: number, newArtistIds: string[]): Promise<void> { await this.favoritesRepo .createQueryBuilder() .update(FavoritesEntity) .set({ artists: newArtistIds }) .where('id = :id', { id: favoriteId }) .execute(); }
修改数组指定位置的元素
PostgreSQL数组下标从1开始,通过下标定位修改:
async updateArtistAtPosition(favoriteId: number, position: number, newArtistId: string): Promise<void> { await this.favoritesRepo .createQueryBuilder() .update(FavoritesEntity) .set({ artists: () => 'artists[:position] = :newArtistId' }) .setParameters({ position, newArtistId, id: favoriteId }) .where('id = :id') .execute(); }
注意事项
- 所有查询构建器示例均使用参数绑定,避免SQL注入风险,禁止直接拼接字符串;
simple-array类型会自动处理数组与逗号分隔字符串的转换,配合PostgreSQL数组类型可正常工作;- 处理大量数据时优先选择查询构建器方式,减少内存占用与数据库交互次数。
内容的提问来源于stack exchange,提问作者Egor
相关产品推荐
相关产品推荐

