Как в Sequelize (TypeScript ) unique:false для связи BelongsToMany (Many-to-Many)
В проекте используется nestJS, PgSQL, orm Sequelize. Есть 3 таблицы: services и visitors, которые связаны между собой (@BelongsToMany), через таблицу visitors_services. Проблема в том, что в базу данных все время запмывается visitors_services_visitor_id_service_id_key, этот uniq мешает работе, как это убрать в коде? Чтобы данной записи не происходило, а связь осталась.
Модель visitor (visitor.model.ts)
import { ApiProperty } from "@nestjs/swagger/dist/decorators";
import { BelongsToMany, Column, DataType, ForeignKey, HasMany, Model, Table, Unique } from "sequelize-typescript";
import { Service } from "src/services/services.model";
import { VisitorService } from "src/visitors_services/visitors_services.model";
interface VisitorCreationAttrs {
/*
...
*/
}
@Table({ tableName: 'visitors' })
export class Visitor extends Model<Visitor, VisitorCreationAttrs>{
@ApiProperty({ example: 1, description: 'PK unic indicate' })
@Column({ type: DataType.INTEGER, unique: true, autoIncrement: true, primaryKey: true })
id: number;
/*
...
*/
@BelongsToMany(() => Service, () => VisitorService)
Services: Service[];
}
Модель services (service.model.ts)
import { ApiProperty } from "@nestjs/swagger/dist/decorators/api-property.decorator";
import { BelongsToMany, Column, DataType, Model, Table } from "sequelize-typescript";
import { Visitor } from "src/visitors/visitor.model";
import { VisitorService } from "src/visitors_services/visitors_services.model";
interface ServiceCreationAttrs {
/*
...
*/
}
@Table({ tableName: 'services' })
export class Service extends Model<Service, ServiceCreationAttrs>{
@ApiProperty({ example: 1, description: 'PK unic indicate' })
@Column({ type: DataType.INTEGER, unique: true, autoIncrement: true, primaryKey: true })
id: number;
/*
...
*/
@BelongsToMany(() => Visitor, () => VisitorService)
Visitors: Visitor[];
}
Модель visitors_services (visitor-service.model.ts)
import { ApiProperty } from "@nestjs/swagger/dist/decorators";
import { Column, DataType, ForeignKey, Model, Table } from "sequelize-typescript";
import { Service } from "src/services/services.model";
import { Visitor } from "src/visitors/visitor.model";
interface VisitorServiceCreationAttrs {
visitor_id: number;
service_id: number;
}
@Table({ tableName: 'visitors_services' })
export class VisitorService extends Model<VisitorService, VisitorServiceCreationAttrs>{
@ApiProperty({ example: 1, description: 'PK unic indicate' })
@Column({ type: DataType.INTEGER, unique: true, autoIncrement: true, primaryKey: true })
id: number;
@ApiProperty({ example: 1, description: 'Ссылка на id посетителя' })
@ForeignKey(() => Visitor)
@Column({ type: DataType.INTEGER, allowNull: false, unique: false })
visitor_id: number;
@ApiProperty({ example: 1, description: 'Ссылка на id услуги' })
@ForeignKey(() => Service)
@Column({ type: DataType.INTEGER, allowNull: false, unique: false })
service_id: number;
}
Ответы (1 шт):
Я пересмотрел данный способ. Видимо в "BelongsToMany" разработчиками было заложено то, что связь уникальна (связь {visitorId: 1, roleId: 1} может встретиться только один раз, при том что может быть {visitorId: 1, roleId: 2} ... {visitorId: 1, roleId: N} ). По этому я решил сделать отношения между своими моделями, как представленно здесь https://sebhastian.com/sequelize-nested-include/.
Данный способ меня устроил. Пока не выявил недостатков для себя.
Изменения в коде:
- В моделях Visitor, Service были удалены строки с @BelongsToMan
- В модель Visitor были добавленны строки:
export class Visitor extends Model<Visitor, VisitorCreationAttrs>{
...
@HasMany(() => VisitorServices)
visitorServices: VisitorServices[]
}
- В модель VisitorService были добавленны строки:
export class VisitorServices extends Model<VisitorServices, VisitorServiceCreationAttrs>{
...
@BelongsTo(() => Service)
service: Service[]
}
Получается что Visitor имеет много VisitorServices, а VisitorServices пренадлежит Services. Данные отношения моделей помогают мне достать данные из бд в виде:
[
{
"name": "VisitorName",
...// VisitorData
"visitorServices": [
{
"id": 1, // visitorServiceId
...// visitorServicesData
"service": {
...// ServiceData
}
},
{
"id": 3,
...
"service": {
...
}
}
]
},
{
"name": "Visitor2Name",
...
"visitorServices": [
{
"id": 2,
...
"service": {
...
}
}
]
}
]
Если вдруг кому потребуется, оставлю тут этот кусок кода для получения данных в виде как описано выше (надеюсь ничего не упустил, если что подправьте):
import { Injectable, Inject } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { Visitor } from './visitor.model';
import { Service } from 'src/services/services.model';
import { VisitorServices } from 'src/visitors_services/visitors_services.model';
export class VisitorsService {
constructor(@InjectModel(Visitor) private visitorRepository: typeof Visitor){ }
async getVisitorsServices(visitorsId: number[]) {
const visitorsServices = await this.visitorRepository.findAll({
where: { id: visitorsId },
include: [
{
model: VisitorServices,
attributes: ['id'],
required: true,
include: [
{
model: Service,
required: true,
attributes: ['price', 'title'],
}
]
}],
attributes: ['name']
});
return visitorsServices
}
}
;)
