feat: allows like to search by many words, adds contain to match exact strings
This commit is contained in:
@@ -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`). |
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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') {
|
||||||
|
|||||||
Reference in New Issue
Block a user