From 46f35156987afcf7ae8342d6a50e327a00b71c5e Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 22 Nov 2023 23:46:55 +0800 Subject: [PATCH] feat: wildcard search for labels and nested labels --- packages/api/src/services/library_item.ts | 61 +++++++++++++++++++---- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/packages/api/src/services/library_item.ts b/packages/api/src/services/library_item.ts index 02d60e1d0..2be6a0311 100644 --- a/packages/api/src/services/library_item.ts +++ b/packages/api/src/services/library_item.ts @@ -156,22 +156,61 @@ const buildWhereClause = ( if (includeLabels && includeLabels.length > 0) { includeLabels.forEach((includeLabel, i) => { const param = `includeLabels_${i}` - queryBuilder.andWhere( - `lower(array_cat(library_item.label_names, library_item.highlight_labels)::text)::text[] && ARRAY[:...${param}]::text[]`, - { - [param]: includeLabel.labels, - } + const hasWildcard = includeLabel.labels.some((label) => + label.includes('*') ) + if (hasWildcard) { + queryBuilder.andWhere( + new Brackets((qb) => { + includeLabel.labels.forEach((label, j) => { + const param = `includeLabels_${i}_${j}` + qb.orWhere( + `array_to_string(array_cat(library_item.label_names, library_item.highlight_labels)::text[], ',') ILIKE :${param}`, + { + [param]: label.replace(/\*/g, '%'), + } + ) + }) + }) + ) + } else { + queryBuilder.andWhere( + `lower(array_cat(library_item.label_names, library_item.highlight_labels)::text)::text[] && ARRAY[:...${param}]::text[]`, + { + [param]: includeLabel.labels, + } + ) + } }) } if (excludeLabels && excludeLabels.length > 0) { - queryBuilder.andWhere( - 'NOT lower(array_cat(library_item.label_names, library_item.highlight_labels)::text)::text[] && ARRAY[:...excludeLabels]::text[]', - { - excludeLabels: excludeLabels.flatMap((filter) => filter.labels), - } - ) + const labels = excludeLabels.flatMap((filter) => filter.labels) + + const hasWildcard = labels.some((label) => label.includes('*')) + + if (hasWildcard) { + queryBuilder.andWhere( + new Brackets((qb) => { + labels.forEach((label, i) => { + const param = `excludeLabels_${i}` + qb.andWhere( + `array_to_string(array_cat(library_item.label_names, library_item.highlight_labels)::text[], ',') NOT ILIKE :${param}`, + { + [param]: label.replace(/\*/g, '%'), + } + ) + }) + }) + ) + } else { + queryBuilder.andWhere( + 'NOT lower(array_cat(library_item.label_names, library_item.highlight_labels)::text)::text[] && ARRAY[:...excludeLabels]::text[]', + { + excludeLabels: labels, + } + ) + } } }