fix slow search resolver without searchTerm input (#9947)

### Issue
Empty searchTerm search resolver 
```
      .orderBy(
        `ts_rank_cd("${SEARCH_VECTOR_FIELD.name}", to_tsquery(:searchTerms))`,
        'DESC',
      )
      .addOrderBy(
        `ts_rank("${SEARCH_VECTOR_FIELD.name}", to_tsquery(:searchTermsOr))`,
        'DESC',
      )
```
builds the following SQL query:
```
ORDER BY
	ts_rank_cd("searchVector", to_tsquery('')) DESC, ts_rank("searchVector", to_tsquery('')) DESC
```

I haven't been able to find doc on this issue, but after testing,
`ts_rank_cd("searchVector", to_tsquery(''))` slows down/freezes my local
db.
As well, ordering by ts_rank is useless without a searchTerm.

### Result
In local, with the imported 300k rows appEvent custom object,
'combinedSearchRecords' gql request with empty searchTerm reduces exec
time from 3s to 300ms.

Co-authored-by: etiennejouan <jouan.etienne@gmail.com>
This commit is contained in:
Etienne
2025-01-31 14:26:19 +01:00
committed by GitHub
parent d946cdcba4
commit 2ab88a6cfe

View File

@ -78,34 +78,41 @@ export class GraphqlQuerySearchResolverService extends GraphqlQueryBaseResolverS
const countQueryBuilder = queryBuilder.clone();
const resultsWithTsVector = (await queryBuilder
.andWhere(
new Brackets((qb) => {
qb.where(
searchTerms === ''
? `"${SEARCH_VECTOR_FIELD.name}" IS NOT NULL`
: `"${SEARCH_VECTOR_FIELD.name}" @@ to_tsquery('simple', :searchTerms)`,
searchTerms === '' ? {} : { searchTerms },
).orWhere(
searchTermsOr === ''
? `"${SEARCH_VECTOR_FIELD.name}" IS NOT NULL`
: `"${SEARCH_VECTOR_FIELD.name}" @@ to_tsquery('simple', :searchTermsOr)`,
searchTermsOr === '' ? {} : { searchTermsOr },
);
}),
)
.orderBy(
`ts_rank_cd("${SEARCH_VECTOR_FIELD.name}", to_tsquery(:searchTerms))`,
'DESC',
)
.addOrderBy(
`ts_rank("${SEARCH_VECTOR_FIELD.name}", to_tsquery(:searchTermsOr))`,
'DESC',
)
.setParameter('searchTerms', searchTerms)
.setParameter('searchTermsOr', searchTermsOr)
.take(limit)
.getMany()) as ObjectRecord[];
const resultsQueryBuilder =
searchTerms !== ''
? queryBuilder
.andWhere(
new Brackets((qb) => {
qb.where(
`"${SEARCH_VECTOR_FIELD.name}" @@ to_tsquery('simple', :searchTerms)`,
{ searchTerms },
).orWhere(
`"${SEARCH_VECTOR_FIELD.name}" @@ to_tsquery('simple', :searchTermsOr)`,
{ searchTermsOr },
);
}),
)
.orderBy(
`ts_rank_cd("${SEARCH_VECTOR_FIELD.name}", to_tsquery(:searchTerms))`,
'DESC',
)
.addOrderBy(
`ts_rank("${SEARCH_VECTOR_FIELD.name}", to_tsquery(:searchTermsOr))`,
'DESC',
)
.setParameter('searchTerms', searchTerms)
.setParameter('searchTermsOr', searchTermsOr)
.take(limit)
: queryBuilder
.andWhere(
new Brackets((qb) => {
qb.where(`"${SEARCH_VECTOR_FIELD.name}" IS NOT NULL`);
}),
)
.take(limit);
const resultsWithTsVector =
(await resultsQueryBuilder.getMany()) as ObjectRecord[];
const objectRecords = formatResult<ObjectRecord[]>(
resultsWithTsVector,