Handle tsvector type columns when forming the db query (#459)

* Support full text search queries

* Handle text search for all query types
This commit is contained in:
prathamesh0 2023-11-09 14:15:31 +05:30 committed by GitHub
parent 483a73fc3e
commit 6860f1a26f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 1 deletions

View File

@ -42,7 +42,8 @@ export const OPERATOR_MAP = {
contains_nocase: 'ILIKE', contains_nocase: 'ILIKE',
starts_nocase: 'ILIKE', starts_nocase: 'ILIKE',
ends_nocase: 'ILIKE', ends_nocase: 'ILIKE',
nested: '' nested: '',
match: '@@'
}; };
const INSERT_EVENTS_BATCH = 100; const INSERT_EVENTS_BATCH = 100;
@ -66,6 +67,8 @@ export interface QueryOptions {
skip?: number; skip?: number;
orderBy?: string; orderBy?: string;
orderDirection?: OrderDirection; orderDirection?: OrderDirection;
tsRankBy?: string;
tsRankValue?: string;
} }
export interface Filter { export interface Filter {
@ -943,6 +946,8 @@ export class Database {
value = this._transformBigValues(value); value = this._transformBigValues(value);
if (operator === 'in') { if (operator === 'in') {
whereClause += '(:...'; whereClause += '(:...';
} else if (columnMetadata.type === 'tsvector' && operator === 'match') {
whereClause += 'to_tsquery(:';
} else { } else {
whereClause += ':'; whereClause += ':';
} }
@ -958,6 +963,10 @@ export class Database {
} }
} }
if (operator === 'match') {
whereClause += ')';
}
if (!columnIsArray) { if (!columnIsArray) {
if (['contains', 'contains_nocase', 'ends', 'ends_nocase'].some(el => el === operator)) { if (['contains', 'contains_nocase', 'ends', 'ends_nocase'].some(el => el === operator)) {
value = `%${value}`; value = `%${value}`;
@ -1173,6 +1182,31 @@ export class Database {
); );
} }
orderTsQuery<Entity extends ObjectLiteral> (
repo: Repository<Entity>,
selectQueryBuilder: SelectQueryBuilder<Entity>,
tsOrderOptions: { tsRankBy?: string, tsRankValue?: string },
columnPrefix = '',
alias?: string
): SelectQueryBuilder<Entity> {
if (!alias) {
alias = selectQueryBuilder.alias;
}
const { tsRankBy, tsRankValue } = tsOrderOptions;
assert(tsRankBy);
const columnMetadata = repo.metadata.findColumnWithPropertyName(tsRankBy);
assert(columnMetadata);
const tsOrderBy = `ts_rank("${alias}"."${columnPrefix}${columnMetadata.databaseName}", to_tsquery('${tsRankValue ?? ''}'))`;
return selectQueryBuilder.addOrderBy(
tsOrderBy,
'ASC'
);
}
async applyBlockHeightFilter<Entity> ( async applyBlockHeightFilter<Entity> (
queryRunner: QueryRunner, queryRunner: QueryRunner,
queryBuilder: SelectQueryBuilder<Entity>, queryBuilder: SelectQueryBuilder<Entity>,

View File

@ -454,6 +454,10 @@ export class GraphDatabase {
selectQueryBuilder = this._baseDatabase.buildQuery(repo, selectQueryBuilder, where, relationsMap.get(entityType), block); selectQueryBuilder = this._baseDatabase.buildQuery(repo, selectQueryBuilder, where, relationsMap.get(entityType), block);
if (queryOptions.tsRankBy) {
selectQueryBuilder = this._baseDatabase.orderTsQuery(repo, selectQueryBuilder, queryOptions);
}
if (queryOptions.orderBy) { if (queryOptions.orderBy) {
selectQueryBuilder = await this._baseDatabase.orderQuery(repo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), block); selectQueryBuilder = await this._baseDatabase.orderQuery(repo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), block);
} }
@ -508,6 +512,10 @@ export class GraphDatabase {
.from(`(${subQuery.getQuery()})`, 'latestEntities') .from(`(${subQuery.getQuery()})`, 'latestEntities')
.setParameters(subQuery.getParameters()) as SelectQueryBuilder<Entity>; .setParameters(subQuery.getParameters()) as SelectQueryBuilder<Entity>;
if (queryOptions.tsRankBy) {
selectQueryBuilder = this._baseDatabase.orderTsQuery(repo, selectQueryBuilder, queryOptions, 'subTable_');
}
if (queryOptions.orderBy) { if (queryOptions.orderBy) {
selectQueryBuilder = await this._baseDatabase.orderQuery(repo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), block, 'subTable_'); selectQueryBuilder = await this._baseDatabase.orderQuery(repo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), block, 'subTable_');
if (queryOptions.orderBy !== 'id') { if (queryOptions.orderBy !== 'id') {
@ -582,6 +590,10 @@ export class GraphDatabase {
selectQueryBuilder = this._baseDatabase.buildQuery(repo, selectQueryBuilder, where, relationsMap.get(entityType), block); selectQueryBuilder = this._baseDatabase.buildQuery(repo, selectQueryBuilder, where, relationsMap.get(entityType), block);
if (queryOptions.tsRankBy) {
selectQueryBuilder = this._baseDatabase.orderTsQuery(repo, selectQueryBuilder, queryOptions);
}
if (queryOptions.orderBy) { if (queryOptions.orderBy) {
selectQueryBuilder = await this._baseDatabase.orderQuery(repo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), block); selectQueryBuilder = await this._baseDatabase.orderQuery(repo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), block);
} }
@ -644,6 +656,10 @@ export class GraphDatabase {
selectQueryBuilder = this._baseDatabase.buildQuery(repo, selectQueryBuilder, where, relationsMap.get(entityType), {}, 'latest'); selectQueryBuilder = this._baseDatabase.buildQuery(repo, selectQueryBuilder, where, relationsMap.get(entityType), {}, 'latest');
if (queryOptions.tsRankBy) {
selectQueryBuilder = this._baseDatabase.orderTsQuery(repo, selectQueryBuilder, queryOptions, '', 'latest');
}
if (queryOptions.orderBy) { if (queryOptions.orderBy) {
selectQueryBuilder = await this._baseDatabase.orderQuery(repo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), {}, '', 'latest'); selectQueryBuilder = await this._baseDatabase.orderQuery(repo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), {}, '', 'latest');
} }
@ -700,6 +716,10 @@ export class GraphDatabase {
selectQueryBuilder = this._baseDatabase.buildQuery(latestEntityRepo, selectQueryBuilder, where, relationsMap.get(entityType), block, 'latest'); selectQueryBuilder = this._baseDatabase.buildQuery(latestEntityRepo, selectQueryBuilder, where, relationsMap.get(entityType), block, 'latest');
if (queryOptions.tsRankBy) {
selectQueryBuilder = this._baseDatabase.orderTsQuery(latestEntityRepo, selectQueryBuilder, queryOptions, '', 'latest');
}
if (queryOptions.orderBy) { if (queryOptions.orderBy) {
selectQueryBuilder = await this._baseDatabase.orderQuery(latestEntityRepo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), block, '', 'latest'); selectQueryBuilder = await this._baseDatabase.orderQuery(latestEntityRepo, selectQueryBuilder, queryOptions, relationsMap.get(entityType), block, '', 'latest');
} }