|
|
@@ -26,7 +26,7 @@ export class MysqlSearchStrategy implements SearchStrategy {
|
|
|
const facetValuesQb = this.connection
|
|
|
.getRepository(SearchIndexItem)
|
|
|
.createQueryBuilder('si')
|
|
|
- .select(['productId', 'productVariantId'])
|
|
|
+ .select(['MIN(productId)', 'MIN(productVariantId)'])
|
|
|
.addSelect('GROUP_CONCAT(facetValueIds)', 'facetValues');
|
|
|
|
|
|
this.applyTermAndFilters(ctx, facetValuesQb, input);
|
|
|
@@ -51,7 +51,7 @@ export class MysqlSearchStrategy implements SearchStrategy {
|
|
|
const qb = this.connection
|
|
|
.getRepository(SearchIndexItem)
|
|
|
.createQueryBuilder('si')
|
|
|
- .select(this.createMysqlsSelect(!!input.groupByProduct));
|
|
|
+ .select(this.createMysqlSelect(!!input.groupByProduct));
|
|
|
if (input.groupByProduct) {
|
|
|
qb.addSelect('MIN(price)', 'minPrice')
|
|
|
.addSelect('MAX(price)', 'maxPrice')
|
|
|
@@ -61,10 +61,10 @@ export class MysqlSearchStrategy implements SearchStrategy {
|
|
|
this.applyTermAndFilters(ctx, qb, input);
|
|
|
if (sort) {
|
|
|
if (sort.name) {
|
|
|
- qb.addOrderBy('productName', sort.name);
|
|
|
+ qb.addOrderBy(input.groupByProduct ? 'MIN(productName)' : 'productName', sort.name);
|
|
|
}
|
|
|
if (sort.price) {
|
|
|
- qb.addOrderBy('price', sort.price);
|
|
|
+ qb.addOrderBy(input.groupByProduct ? 'MIN(price)' : 'price', sort.price);
|
|
|
}
|
|
|
} else {
|
|
|
if (input.term && input.term.length > this.minTermLength) {
|
|
|
@@ -88,7 +88,7 @@ export class MysqlSearchStrategy implements SearchStrategy {
|
|
|
this.connection
|
|
|
.getRepository(SearchIndexItem)
|
|
|
.createQueryBuilder('si')
|
|
|
- .select(this.createMysqlsSelect(!!input.groupByProduct)),
|
|
|
+ .select(this.createMysqlSelect(!!input.groupByProduct)),
|
|
|
input,
|
|
|
);
|
|
|
if (enabledOnly) {
|
|
|
@@ -110,26 +110,32 @@ export class MysqlSearchStrategy implements SearchStrategy {
|
|
|
): SelectQueryBuilder<SearchIndexItem> {
|
|
|
const { term, facetValueIds, facetValueOperator, collectionId, collectionSlug } = input;
|
|
|
|
|
|
- qb.where('1 = 1');
|
|
|
if (term && term.length > this.minTermLength) {
|
|
|
- qb.addSelect(`IF (sku LIKE :like_term, 10, 0)`, 'sku_score')
|
|
|
+ const termScoreQuery = this.connection
|
|
|
+ .getRepository(SearchIndexItem)
|
|
|
+ .createQueryBuilder('si_inner')
|
|
|
+ .select('si_inner.productId', 'inner_productId')
|
|
|
+ .addSelect('si_inner.productVariantId', 'inner_productVariantId')
|
|
|
+ .addSelect(`IF (sku LIKE :like_term, 10, 0)`, 'sku_score')
|
|
|
.addSelect(
|
|
|
- `
|
|
|
- (SELECT sku_score) +
|
|
|
- MATCH (productName) AGAINST (:term) * 2 +
|
|
|
- MATCH (productVariantName) AGAINST (:term) * 1.5 +
|
|
|
- MATCH (description) AGAINST (:term)* 1`,
|
|
|
+ `(SELECT sku_score) +
|
|
|
+ MATCH (productName) AGAINST (:term) * 2 +
|
|
|
+ MATCH (productVariantName) AGAINST (:term) * 1.5 +
|
|
|
+ MATCH (description) AGAINST (:term)* 1`,
|
|
|
'score',
|
|
|
)
|
|
|
- .andWhere(
|
|
|
- new Brackets(qb1 => {
|
|
|
- qb1.where('sku LIKE :like_term')
|
|
|
- .orWhere('MATCH (productName) AGAINST (:term)')
|
|
|
- .orWhere('MATCH (productVariantName) AGAINST (:term)')
|
|
|
- .orWhere('MATCH (description) AGAINST (:term)');
|
|
|
- }),
|
|
|
- )
|
|
|
+ .where('sku LIKE :like_term')
|
|
|
+ .orWhere('MATCH (productName) AGAINST (:term)')
|
|
|
+ .orWhere('MATCH (productVariantName) AGAINST (:term)')
|
|
|
+ .orWhere('MATCH (description) AGAINST (:term)')
|
|
|
.setParameters({ term, like_term: `%${term}%` });
|
|
|
+
|
|
|
+ qb.innerJoin(`(${termScoreQuery.getQuery()})`, 'term_result', 'inner_productId = si.productId')
|
|
|
+ .addSelect(input.groupByProduct ? 'MAX(term_result.score)' : 'term_result.score', 'score')
|
|
|
+ .andWhere('term_result.inner_productVariantId = si.productVariantId')
|
|
|
+ .setParameters(termScoreQuery.getParameters());
|
|
|
+ } else {
|
|
|
+ qb.addSelect('1 as score');
|
|
|
}
|
|
|
if (facetValueIds?.length) {
|
|
|
qb.andWhere(
|
|
|
@@ -166,7 +172,7 @@ export class MysqlSearchStrategy implements SearchStrategy {
|
|
|
* then all selected columns must be aggregated. So we just apply the
|
|
|
* "MIN" function in this case to all other columns than the productId.
|
|
|
*/
|
|
|
- private createMysqlsSelect(groupByProduct: boolean): string {
|
|
|
+ private createMysqlSelect(groupByProduct: boolean): string {
|
|
|
return fieldsToSelect
|
|
|
.map(col => {
|
|
|
const qualifiedName = `si.${col}`;
|