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

NestJS中如何检测数据库数组字段内数据是否已存在

问题:无法检测数据库中是否存在指定用户组合的对话

实体定义

@Entity()
class ChatConversation {
  @Column('simple-array')
  users: string[];
  // 其他字段省略
}

数据库现有数据

{
  "id": "57b41c65-ae8d-4cf0-8246-a85f296cf1ce",
  "createdAt": "2023-10-14T10:07:44.386Z",
  "updatedAt": "2023-10-14T10:07:44.386Z",
  "deletedAt": null,
  "users": [
    "888ce1ad-8ee4-4518-977a-78b66275ee9d",
    "529938d1-33fd-4aa1-bd2a-9eb741b5c19f"
  ]
}

当前检测代码(存在问题)

public async testData(
  firstUserId: string,
  body: AddConversationDto,
): { // 语法错误:缺少返回类型定义,应为 Promise<{ message: string }>
  const { userId } = body;
  const conversation = await this.chatConversationRepositoryService.findMany({
    users: In[userId], // 语法错误:In是函数,需调用In([userId]);逻辑错误:仅查询包含单个用户的对话
  });

  if (conversation) // 逻辑错误:findMany返回数组,空数组仍会被判定为true
    return { message: this.i18nService.t('systemMessage.addConversation') };

  await this.chatConversationRepositoryService.save({
    users: [firstUserId, userId],
  });

  return { message: this.i18nService.t('systemMessage.addConversation') };
}

问题分析

  1. 语法错误:In[userId] 写法错误,TypeORM的In操作符需以函数形式调用 In([userId])。
  2. 逻辑偏差:你实际需要检测「同时包含firstUserId和userId的对话是否存在」,但当前查询仅匹配包含单个userId的所有对话,范围不符合需求。
  3. 判断错误:findMany返回数组,即使无匹配数据返回空数组[],在JS中空数组属于真值,if (conversation) 永远为true,导致不会执行后续保存逻辑。
  4. 存储适配:TypeORM的simple-array在不同数据库存储形式不同:
    • PostgreSQL:原生数组类型
    • MySQL/其他:逗号分隔的字符串

修正方案

针对PostgreSQL(原生数组存储)

使用ArrayContaining操作符精确匹配同时包含两个用户的数组:

import { ArrayContaining } from "typeorm";

public async testData(
  firstUserId: string,
  body: AddConversationDto,
): Promise<{ message: string }> {
  const { userId } = body;
  
  // 查询同时包含两个用户的对话
  const conversations = await this.chatConversationRepositoryService.findMany({
    where: {
      users: ArrayContaining([firstUserId, userId])
    }
  });

  // 检查是否存在匹配的对话
  if (conversations.length > 0) {
    return { message: this.i18nService.t('systemMessage.conversationExists') };
  }

  await this.chatConversationRepositoryService.save({
    users: [firstUserId, userId],
  });

  return { message: this.i18nService.t('systemMessage.addConversationSuccess') };
}

针对MySQL(逗号分隔字符串存储)

通过Like组合条件匹配包含两个用户ID的字符串:

import { And, Like } from "typeorm";

public async testData(
  firstUserId: string,
  body: AddConversationDto,
): Promise<{ message: string }> {
  const { userId } = body;
  
  // 查询同时包含两个用户ID的对话
  const conversations = await this.chatConversationRepositoryService.findMany({
    where: {
      users: And(Like(`%${firstUserId}%`), Like(`%${userId}%`))
    }
  });

  if (conversations.length > 0) {
    return { message: this.i18nService.t('systemMessage.conversationExists') };
  }

  await this.chatConversationRepositoryService.save({
    users: [firstUserId, userId],
  });

  return { message: this.i18nService.t('systemMessage.addConversationSuccess') };
}

额外说明

  • 建议区分「对话已存在」和「创建成功」的提示文案,避免用户混淆。
  • 如果需要严格匹配仅包含这两个用户的对话(不包含其他用户),PostgreSQL可使用ArrayEquals,MySQL则需要先对用户ID排序再存储和查询,确保字符串顺序一致后做精确匹配。

内容的提问来源于stack exchange,提问作者Duru015

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:34:57