added index on media entity_id, report query with unindexed fields

This commit is contained in:
dswbx
2025-02-22 22:09:50 +01:00
parent b8f87a2097
commit 9a741f49a0
4 changed files with 26 additions and 8 deletions

View File

@@ -73,6 +73,7 @@ export abstract class Connection<DB = any> {
return false; return false;
} }
// @todo: add if only first field is used in index
supportsIndices(): boolean { supportsIndices(): boolean {
return false; return false;
} }

View File

@@ -8,6 +8,7 @@ import {
UnableToConnectException UnableToConnectException
} from "../errors"; } from "../errors";
import { MutatorEvents, RepositoryEvents } from "../events"; import { MutatorEvents, RepositoryEvents } from "../events";
import type { Field } from "../fields/Field";
import type { EntityIndex } from "../fields/indices/EntityIndex"; import type { EntityIndex } from "../fields/indices/EntityIndex";
import type { EntityRelation } from "../relations"; import type { EntityRelation } from "../relations";
import { RelationAccessor } from "../relations/RelationAccessor"; import { RelationAccessor } from "../relations/RelationAccessor";
@@ -142,6 +143,16 @@ export class EntityManager<TBD extends object = DefaultDB> {
return this.indices.some((e) => e.name === name); return this.indices.some((e) => e.name === name);
} }
// @todo: add to Connection whether first index is used or not
getIndexedFields(_entity: Entity | string): Field[] {
const entity = this.entity(_entity);
const indices = this.getIndicesOf(entity);
const rel_fields = entity.fields.filter((f) => f.type === "relation");
// assuming only first
const idx_fields = indices.map((index) => index.fields[0]);
return [entity.getPrimaryField(), ...rel_fields, ...idx_fields].filter(Boolean) as Field[];
}
addRelation(relation: EntityRelation) { addRelation(relation: EntityRelation) {
// check if entities are registered // check if entities are registered
if (!this.entity(relation.source.entity.name) || !this.entity(relation.target.entity.name)) { if (!this.entity(relation.source.entity.name) || !this.entity(relation.target.entity.name)) {

View File

@@ -66,6 +66,13 @@ export class Repository<TBD extends object = DefaultDB, TB extends keyof TBD = a
return this.em.connection.kysely; return this.em.connection.kysely;
} }
private checkIndex(entity: string, field: string, clause: string) {
const indexed = this.em.getIndexedFields(entity).map((f) => f.name);
if (!indexed.includes(field)) {
$console.warn(`Field "${entity}.${field}" used in "${clause}" is not indexed`);
}
}
getValidOptions(options?: Partial<RepoQuery>): RepoQuery { getValidOptions(options?: Partial<RepoQuery>): RepoQuery {
const entity = this.entity; const entity = this.entity;
// @todo: if not cloned deep, it will keep references and error if multiple requests come in // @todo: if not cloned deep, it will keep references and error if multiple requests come in
@@ -85,6 +92,7 @@ export class Repository<TBD extends object = DefaultDB, TB extends keyof TBD = a
throw new InvalidSearchParamsException(`Invalid sort direction "${options.sort.dir}"`); throw new InvalidSearchParamsException(`Invalid sort direction "${options.sort.dir}"`);
} }
this.checkIndex(entity.name, options.sort.by, "sort");
validated.sort = options.sort; validated.sort = options.sort;
} }
@@ -137,9 +145,11 @@ export class Repository<TBD extends object = DefaultDB, TB extends keyof TBD = a
return true; return true;
} }
this.checkIndex(alias, prop, "where");
return !this.em.entity(alias).getField(prop); return !this.em.entity(alias).getField(prop);
} }
this.checkIndex(entity.name, field, "where");
return typeof entity.getField(field) === "undefined"; return typeof entity.getField(field) === "undefined";
}); });
@@ -255,12 +265,6 @@ export class Repository<TBD extends object = DefaultDB, TB extends keyof TBD = a
...config?.defaults ...config?.defaults
}; };
/*$console.log("build query options", {
entity: entity.name,
options,
config
});*/
if (!ignore.includes("select") && options.select) { if (!ignore.includes("select") && options.select) {
qb = qb.select(entity.getAliasedSelectFrom(options.select, alias)); qb = qb.select(entity.getAliasedSelectFrom(options.select, alias));
} }
@@ -299,7 +303,9 @@ export class Repository<TBD extends object = DefaultDB, TB extends keyof TBD = a
return { return {
qb: this.addOptionsToQueryBuilder(undefined, options, { qb: this.addOptionsToQueryBuilder(undefined, options, {
ignore, ignore,
alias: entity.name alias: entity.name,
// already done
validate: false
}), }),
options options
}; };

View File

@@ -51,7 +51,7 @@ export class AppMedia extends Module<typeof mediaConfigSchema> {
const media = this.getMediaEntity(true); const media = this.getMediaEntity(true);
this.ensureSchema( this.ensureSchema(
em({ [media.name as "media"]: media }, ({ index }, { media }) => { em({ [media.name as "media"]: media }, ({ index }, { media }) => {
index(media).on(["path"], true).on(["reference"]); index(media).on(["path"], true).on(["reference"]).on(["entity_id"]);
}) })
); );
} catch (e) { } catch (e) {