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') }; }
问题分析
- 语法错误:
In[userId]写法错误,TypeORM的In操作符需以函数形式调用In([userId])。 - 逻辑偏差:你实际需要检测「同时包含
firstUserId和userId的对话是否存在」,但当前查询仅匹配包含单个userId的所有对话,范围不符合需求。 - 判断错误:
findMany返回数组,即使无匹配数据返回空数组[],在JS中空数组属于真值,if (conversation)永远为true,导致不会执行后续保存逻辑。 - 存储适配: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
相关产品推荐
相关产品推荐

