Заказ 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
должен работать из коробки