Заказ Mikro-orm по ST_Distance_Sphere с использованием драйвера MySQL

С MySQL я пытаюсь заказать ST_Distance_Sphere с помощью QueryBuilder.

У меня есть сущность:

import { Entity, PrimaryKey, Property } from "mikro-orm";

@Entity({ tableName: "studio" })
export default class StudioEntity {
    @PrimaryKey()
    public id!: number;

    @Property()
    public name!: string;

    @Property({ columnType: "point srid 4326" })
    public geometry!: object;
}

И я пытаюсь:

export default class StudioStore {
    private studioRepository: EntityRepository<StudioEntity>;

    public constructor(ormClient: OrmClient) {
        this.studioRepository = ormClient.em.getRepository(StudioEntity);
    }

    public async findPage(first: number): Promise<StudioEntity[]> {
        const query = this.studioRepository.createQueryBuilder().select("*");

        query.addSelect(
            "ST_Distance_Sphere(`e0`.`geometry`, ST_GeomFromText('POINT(28.612849 77.229883)', 4326)) as distance",
        );

        query.orderBy({ distance: "ASC" });

        return query.limit(first).getResult();
    }
}

Но получаю ошибку ORM:

Попытка выполнить запрос по несуществующему свойству StudioEntity.distance

Итак, я пытаюсь добавить свойство к сущности:

    @Property({ persist: false })
    public distance?: number;

Но теперь я получаю ошибку MySQL:

Неизвестный столбец e0.distance в предложении заказа

Это сгенерированный SQL-запрос:

[query] select `e0`.*, ST_Distance_Sphere(`e0`.`geometry`, ST_GeomFromText('POINT(28.612849 77.229883)', 4326)) as distance from `studio` as `e0` order by `e0`.`distance` asc limit 5 [took 4 ms]

1 ответ

Решение

Вам нужно будет вернуться к knex, поскольку QB в настоящее время поддерживает только определенные поля свойств по порядку. Вам также необходимо определить этот виртуальныйdistance свойство, как вы уже сделали, поэтому значение можно сопоставить с сущностью.

https://mikro-orm.io/docs/query-builder/

const query = this.studioRepository.createQueryBuilder().select("*");
query.addSelect("ST_Distance_Sphere(`e0`.`geometry`, ST_GeomFromText('POINT(28.612849 77.229883)', 4326)) as distance");
query.limit(first);
const knex = query.getKnexQuery();
knex.orderBy('distance', 'asc');
const res = await this.em.getConnection().execute(knex);
const entities = res.map(a => this.em.map(StudioEntity, a));

Не очень приятно, надо сказать, совсем забыл, что можно заказывать по вычисленным полям. Постараемся решить эту проблему в версии 4. Я думаю, что это может даже работать как ваш второй подход, поскольку QB может просто проверить, является ли свойство виртуальным (имеетpersist: false), и тогда он не будет префиксом.

изменить: с версии 3.6.6 подход с persist: false должен работать из коробки

Другие вопросы по тегам