feat: allows like to search by many words, adds contain to match exact strings

This commit is contained in:
James
2022-04-05 16:22:57 -04:00
parent b99f6b16af
commit ec91757257
5 changed files with 35 additions and 18 deletions

View File

@@ -59,7 +59,8 @@ The above example demonstrates a simple query but you can get much more complex.
| `greater_than_equal` | For numeric or date-based fields. | | `greater_than_equal` | For numeric or date-based fields. |
| `less_than` | For numeric or date-based fields. | | `less_than` | For numeric or date-based fields. |
| `less_than_equal` | For numeric or date-based fields. | | `less_than_equal` | For numeric or date-based fields. |
| `like` | The value must partially match. | | `like` | Case-insensitive string must be present. If string of words, all words must be present, in any order. |
| `contains` | Must contain the value entered, case-insensitive. |
| `in` | The value must be found within the provided comma-delimited list of values. | | `in` | The value must be found within the provided comma-delimited list of values. |
| `not_in` | The value must NOT be within the provided comma-delimited list of values. | | `not_in` | The value must NOT be within the provided comma-delimited list of values. |
| `exists` | Only return documents where the value either exists (`true`) or does not exist (`false`). | | `exists` | Only return documents where the value either exists (`true`) or does not exist (`false`). |

View File

@@ -62,26 +62,31 @@ const like = {
value: 'like', value: 'like',
}; };
const contains = {
label: 'contains',
value: 'contains',
};
const fieldTypeConditions = { const fieldTypeConditions = {
text: { text: {
component: 'Text', component: 'Text',
operators: [...base, like], operators: [...base, like, contains],
}, },
email: { email: {
component: 'Text', component: 'Text',
operators: [...base, like], operators: [...base, contains],
}, },
textarea: { textarea: {
component: 'Text', component: 'Text',
operators: [...base, like], operators: [...base, like, contains],
},
wysiwyg: {
component: 'Text',
operators: [...base, like],
}, },
code: { code: {
component: 'Text', component: 'Text',
operators: [...base, like], operators: [...base, like, contains],
},
richText: {
component: 'Text',
operators: [...base, like, contains],
}, },
number: { number: {
component: 'Number', component: 'Number',

View File

@@ -44,7 +44,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field, field,
type, type,
parentName, parentName,
[...operators.equality, 'like'], [...operators.equality, 'like', 'contains'],
), ),
}; };
}, },
@@ -55,7 +55,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field, field,
type, type,
parentName, parentName,
[...operators.equality, 'like'], [...operators.equality, 'like', 'contains'],
), ),
}; };
}, },
@@ -66,7 +66,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field, field,
type, type,
parentName, parentName,
[...operators.equality, 'like'], [...operators.equality, 'like', 'contains'],
), ),
}; };
}, },
@@ -77,7 +77,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field, field,
type, type,
parentName, parentName,
[...operators.equality, 'like'], [...operators.equality, 'like', 'contains'],
), ),
}; };
}, },
@@ -88,7 +88,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field, field,
type, type,
parentName, parentName,
[...operators.equality, 'like'], [...operators.equality, 'like', 'contains'],
), ),
}; };
}, },
@@ -116,7 +116,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
}, {}), }, {}),
}), }),
parentName, parentName,
[...operators.equality, 'like'], [...operators.equality, 'like', 'contains'],
), ),
}), }),
date: (field: DateField) => { date: (field: DateField) => {

View File

@@ -8,7 +8,7 @@ import { getSchemaTypeOptions } from './getSchemaTypeOptions';
import { operatorMap } from './operatorMap'; import { operatorMap } from './operatorMap';
import { sanitizeQueryValue } from './sanitizeFormattedValue'; import { sanitizeQueryValue } from './sanitizeFormattedValue';
const validOperators = ['like', 'in', 'all', 'not_in', 'greater_than_equal', 'greater_than', 'less_than_equal', 'less_than', 'not_equals', 'equals', 'exists', 'near']; const validOperators = ['like', 'contains', 'in', 'all', 'not_in', 'greater_than_equal', 'greater_than', 'less_than_equal', 'less_than', 'not_equals', 'equals', 'exists', 'near'];
const subQueryOptions = { const subQueryOptions = {
limit: 50, limit: 50,

View File

@@ -90,8 +90,19 @@ export const sanitizeQueryValue = (schemaType: SchemaType, path: string, operato
} }
} }
if (operator === 'like' && path !== '_id') { if (path !== '_id') {
formattedValue = { $regex: formattedValue, $options: 'i' }; if (operator === 'contains') {
formattedValue = { $regex: formattedValue, $options: 'i' };
}
if (operator === 'like' && typeof formattedValue === 'string') {
const words = formattedValue.split(' ');
const regex = words.reduce((pattern, word, i) => {
return `${pattern}(?=.*\\b${word}\\b)${i + 1 === words.length ? '.+' : ''}`;
}, '');
formattedValue = { $regex: new RegExp(regex), $options: 'i' };
}
} }
if (operator === 'exists') { if (operator === 'exists') {