NestJS TypeORM error on updating entity with list of sub-entities

17 Views Asked by At

I am having issues updating my Chat entity with new messages. I have tried different methods and am currently getting Error: Cannot query across one-to-many for property messages

chat.entity.ts

import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
  JoinColumn,
  OneToMany,
  OneToOne,
} from 'typeorm';
import { ApiProperty } from '@nestjs/swagger';
import { ChatMessage } from '../chatMessage/chatMessage.entity';
import { User } from 'src/auth/user.entity';
import { Session } from 'src/sessions/session.entity';

@Entity()
export class Chat {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToOne(() => User, (user) => user.chats)
  @ApiProperty({
    type: () => User,
  })
  user: User;

  @ApiProperty({
    example: '2024-02-09T22:15:11.293Z',
    description: 'session_id',
  })
  @Column()
  session_id: string;

  @ApiProperty({
    type: () => Session,
    example: '',
    description: '',
  })
  @OneToOne(() => Session)
  @JoinColumn()
  session: Session;

  @ApiProperty({
    type: () => ChatMessage,
    example: '',
    description: 'chat message',
  })
  @OneToMany(() => ChatMessage, (chatMessage) => chatMessage.chat)
  @Column('jsonb', { default: [] })
  @JoinColumn()
  messages: ChatMessage[];
}

chatMessage.entity.ts

import {
  Entity,
  Column,
  PrimaryGeneratedColumn,
  OneToMany,
  JoinColumn,
} from 'typeorm';
import { ApiProperty } from '@nestjs/swagger';
import { Chat } from '../chat/chat.entity';

export class DataDto {
  // Not sure why type is in both objects but that's how langchain structures it.
  @ApiProperty({ example: 'human', description: 'type' })
  @Column()
  type: string;

  @ApiProperty({
    example:
      'Mr. Smith is an investment banker at a large bank and primarily works with water risk data. What product or products should we recommend?',
    description: 'content',
  })
  @Column()
  content: string;

  @Column('jsonb', { nullable: true })
  additional_kwargs: any; // TODO: Figure out how to define this type

  @ApiProperty({ example: false, description: 'Bool for example' })
  @Column()
  example: boolean;
}

@Entity()
export class ChatMessage {
  @PrimaryGeneratedColumn()
  id: number;

  @ApiProperty({
    type: () => Chat,
    example: '',
    description: '',
  })
  @OneToMany(() => Chat, (chat: Chat) => chat.messages)
  @JoinColumn()
  chat: Chat;

  @ApiProperty({
    example: 'human',
    description: 'type',
    nullable: true,
    enum: ['human', 'bot'],
  })
  @Column({ nullable: true, enum: ['human', 'bot'] })
  type: string;

  @Column('jsonb', { nullable: true })
  data: DataDto;
}

chat.service.ts

@Injectable()
export class ChatService {
  constructor(
    @InjectRepository(Chat)
    private chatRepository: Repository<Chat>,
  ) {}
  async patch(id: number, Chat: Partial<Chat>): Promise<any> {
    const chat = await this.chatRepository.findOne({ where: { id } });
    if (!chat) {
      throw new Error('Chat not found');
    }
    console.debug('ChatService.patch chat:', chat);
    console.debug('ChatService.patch Chat:', Chat);
    const concatenatedMessages = chat.messages.concat(Chat.messages);
    console.debug(
      'ChatService.patch concatenatedMessages:',
      concatenatedMessages,
    );
    return await this.chatRepository.update(id, {
      messages: concatenatedMessages,
    });
1

There are 1 best solutions below

0
CreativeUsername On

figured it out:

chatMessage.entity.ts: replace @OneToMany in ChatMessage.chat with @ManyToOne

chat.entity.ts: remove @JoinColumn() in Chat.messages

chat.service.ts: update with const chat = await this.chatRepository.findOne({ where: { id }, relations: { messages: true }, });