You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 10:24:11