Skip to content

Commit

Permalink
feat: allows like to search by many words, adds contain to match exac…
Browse files Browse the repository at this point in the history
…t strings
  • Loading branch information
jmikrut committed Apr 5, 2022
1 parent b99f6b1 commit ec91757
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 17 deletions.
3 changes: 2 additions & 1 deletion docs/queries/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
| `less_than` | 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. |
| `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`). |
Expand Down
19 changes: 12 additions & 7 deletions src/admin/components/elements/WhereBuilder/field-types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,26 +62,31 @@ const like = {
value: 'like',
};

const contains = {
label: 'contains',
value: 'contains',
};

const fieldTypeConditions = {
text: {
component: 'Text',
operators: [...base, like],
operators: [...base, like, contains],
},
email: {
component: 'Text',
operators: [...base, like],
operators: [...base, contains],
},
textarea: {
component: 'Text',
operators: [...base, like],
operators: [...base, like, contains],
},
wysiwyg: {
code: {
component: 'Text',
operators: [...base, like],
operators: [...base, like, contains],
},
code: {
richText: {
component: 'Text',
operators: [...base, like],
operators: [...base, like, contains],
},
number: {
component: 'Number',
Expand Down
12 changes: 6 additions & 6 deletions src/graphql/schema/fieldToSchemaMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field,
type,
parentName,
[...operators.equality, 'like'],
[...operators.equality, 'like', 'contains'],
),
};
},
Expand All @@ -55,7 +55,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field,
type,
parentName,
[...operators.equality, 'like'],
[...operators.equality, 'like', 'contains'],
),
};
},
Expand All @@ -66,7 +66,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field,
type,
parentName,
[...operators.equality, 'like'],
[...operators.equality, 'like', 'contains'],
),
};
},
Expand All @@ -77,7 +77,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field,
type,
parentName,
[...operators.equality, 'like'],
[...operators.equality, 'like', 'contains'],
),
};
},
Expand All @@ -88,7 +88,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
field,
type,
parentName,
[...operators.equality, 'like'],
[...operators.equality, 'like', 'contains'],
),
};
},
Expand Down Expand Up @@ -116,7 +116,7 @@ const fieldToSchemaMap: (parentName: string) => any = (parentName: string) => ({
}, {}),
}),
parentName,
[...operators.equality, 'like'],
[...operators.equality, 'like', 'contains'],
),
}),
date: (field: DateField) => {
Expand Down
2 changes: 1 addition & 1 deletion src/mongoose/buildQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getSchemaTypeOptions } from './getSchemaTypeOptions';
import { operatorMap } from './operatorMap';
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 = {
limit: 50,
Expand Down
15 changes: 13 additions & 2 deletions src/mongoose/sanitizeFormattedValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,19 @@ export const sanitizeQueryValue = (schemaType: SchemaType, path: string, operato
}
}

if (operator === 'like' && path !== '_id') {
formattedValue = { $regex: formattedValue, $options: 'i' };
if (path !== '_id') {
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') {
Expand Down

0 comments on commit ec91757

Please sign in to comment.