Каскад микро-orm.УДАЛИТЬ, это только для СУБД?

#mikro-orm

#mikro-orm

Вопрос:

Я использую mikro-orm с MongoDB и пытаюсь выполнить каскад.УДАЛИТЬ, но я не могу заставить его работать.

Бизнес-объект:

 @Entity({ collection: "business" })
export class BusinessModel implements BusinessEntity {
    @PrimaryKey()
    public _id!: ObjectId;

    @Property()
    public name!: string;

    @Property()
    public description!: string;

    @OneToMany({ entity: () => LocationModel, fk: "business", cascade: [Cascade.ALL] })
    public locations: Collection<LocationModel> = new Collection(this);
}

export interface BusinessModel extends IEntity<string> { }
  

Объект местоположения:

 @Entity({ collection: "location" })
export class LocationModel implements LocationEntity {
    @PrimaryKey()
    public _id!: ObjectId;

    @Property()
    public geometry!: GeometryEmbedded;

    @ManyToOne({ entity: () => BusinessModel})
    public business!: BusinessModel;

    public distance?: number;
}

export interface LocationModel extends IEntity<string> { }
  

Бизнес-данные:

 _id: 5cac818273243d1439866227
name: "Prueba"
description: "Prueba eliminacion"
  

Данные о местоположении:

 _id: 5cac9807179e380df8e43b6c
geometry: Object
business: 5cac818273243d1439866227

_id: 5cacc941c55fbb0854f86939
geometry: Object
business: 5cac818273243d1439866227
  

И код:

 export default class BusinessData {
    private businessRepository: EntityRepository<BusinessModel>;

    public constructor(@inject(OrmClient) ormClient: OrmClient) {
        this.businessRepository = ormClient.em.getRepository(BusinessModel);
    }

    public async delete(id: string): Promise<number> {
        return await this.businessRepository.remove(id);
    }
}
  

«Бизнес» правильно удален, но все связанные с ним «местоположения» сохраняются там.

Журнал показывает только:

[регистратор запросов] db.getCollection(«бизнес»).deleteMany() [заняло 0 мс]

Комментарии:

1. Просто любопытно — вы действительно получили это из регистратора запросов или вы удалили часть where? Если да, вы уверены, что указываете значение для id параметра?

2. Нет, я не удалял часть where, и я предоставил значение для параметра id. Изменение кода на: public async delete(id: string): Promise<number> { // tslint:disable-next-line: no-console console.log(id); return await this.businessRepository.remove(id); } Вот результат после обнаружения объекта, ничего не удаляя: 5cac818273243d1439866227 [query-logger] db.getCollection("business").deleteMany() [took 0 ms]

3. Только что проверил код, его нет только в регистраторе запросов, условие не пропущено при запросе к базе данных. Исправлю это как можно скорее, выглядит довольно страшно :]

Ответ №1:

Каскады работают на уровне приложений, поэтому для всех драйверов, включая mongo.

Проблема здесь в том, что вы удаляете Business объект по идентификатору. Вам нужно удалить его по ссылке — укажите объект и убедитесь, что у вас заполнена коллекция, иначе ORM не знает, какие объекты нужно каскадно удалять.

Попробуйте так:

 export default class BusinessData {
  public async delete(id: string): Promise<number> {
    const business = await this.businessRepository.findOne(id, ['locations'])
    return await this.businessRepository.remove(business);
  }
}
  

Ваш подход с удалением по идентификатору будет работать, только если объект уже загружен в identity map (он же управляемый EM), включая locations коллекцию.

Комментарии:

1. Да, это работает. Спасибо (надеюсь, я не слишком беспокою)

2. Абсолютно нет! Спасибо за хорошие вопросы! В ближайшем будущем я создам страницу часто задаваемых вопросов на их основе.