fix(search): Implement implicit AND logic for mixed simple term and field:value queries in search
This commit is contained in:
parent
419eb163f4
commit
6c50bd23ec
@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-04-22 - 5.11.4 - fix(search)
|
||||||
|
Implement implicit AND logic for mixed simple term and field:value queries in search
|
||||||
|
|
||||||
|
- Added a new branch to detect and handle search queries that mix field:value pairs with plain terms without explicit operators
|
||||||
|
- Builds an implicit $and filter when query parts contain colon(s) but lack explicit boolean operators or quotes
|
||||||
|
- Ensures proper parsing and improved robustness of search filters
|
||||||
|
|
||||||
## 2025-04-22 - 5.11.3 - fix(lucene adapter and search tests)
|
## 2025-04-22 - 5.11.3 - fix(lucene adapter and search tests)
|
||||||
Improve range query parsing in Lucene adapter and expand search test coverage
|
Improve range query parsing in Lucene adapter and expand search test coverage
|
||||||
|
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartdata',
|
name: '@push.rocks/smartdata',
|
||||||
version: '5.11.3',
|
version: '5.11.4',
|
||||||
description: 'An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.'
|
description: 'An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.'
|
||||||
}
|
}
|
||||||
|
@ -379,6 +379,34 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
|
|||||||
const orConds = searchableFields.map((f) => ({ [f]: { $regex: pattern, $options: 'i' } }));
|
const orConds = searchableFields.map((f) => ({ [f]: { $regex: pattern, $options: 'i' } }));
|
||||||
return await (this as any).getInstances({ $or: orConds });
|
return await (this as any).getInstances({ $or: orConds });
|
||||||
}
|
}
|
||||||
|
// implicit AND for mixed simple term + field:value queries (no explicit operators)
|
||||||
|
const parts = q.split(/\s+/);
|
||||||
|
const hasColon = parts.some((t) => t.includes(':'));
|
||||||
|
// implicit AND for mixed simple term + field:value queries (no explicit operators or range syntax)
|
||||||
|
if (
|
||||||
|
parts.length > 1 && hasColon &&
|
||||||
|
!q.includes(' AND ') && !q.includes(' OR ') && !q.includes(' NOT ') &&
|
||||||
|
!q.includes('(') && !q.includes(')') && !q.includes('[') && !q.includes(']') &&
|
||||||
|
!q.includes('"') && !q.includes("'") &&
|
||||||
|
!q.includes('*') && !q.includes('?')
|
||||||
|
) {
|
||||||
|
const andConds = parts.map((term) => {
|
||||||
|
const m = term.match(/^(\\w+):([^"'\\*\\?\\s]+)$/);
|
||||||
|
if (m) {
|
||||||
|
const field = m[1];
|
||||||
|
const value = m[2];
|
||||||
|
if (!searchableFields.includes(field)) {
|
||||||
|
throw new Error(`Field '${field}' is not searchable for class ${this.name}`);
|
||||||
|
}
|
||||||
|
return { [field]: value };
|
||||||
|
} else {
|
||||||
|
const esc = escapeForRegex(term);
|
||||||
|
const ors = searchableFields.map((f) => ({ [f]: { $regex: esc, $options: 'i' } }));
|
||||||
|
return { $or: ors };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return await (this as any).getInstances({ $and: andConds });
|
||||||
|
}
|
||||||
// detect advanced Lucene syntax: field:value, wildcards, boolean, grouping
|
// detect advanced Lucene syntax: field:value, wildcards, boolean, grouping
|
||||||
const luceneSyntax = /(\w+:[^\s]+)|\*|\?|\bAND\b|\bOR\b|\bNOT\b|\(|\)/;
|
const luceneSyntax = /(\w+:[^\s]+)|\*|\?|\bAND\b|\bOR\b|\bNOT\b|\(|\)/;
|
||||||
if (luceneSyntax.test(q)) {
|
if (luceneSyntax.test(q)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user