Compare commits

...

4 Commits

Author SHA1 Message Date
419eb163f4 5.11.3
Some checks failed
Default (tags) / security (push) Successful in 40s
Default (tags) / test (push) Successful in 3m6s
Default (tags) / release (push) Failing after 51s
Default (tags) / metadata (push) Successful in 57s
2025-04-22 18:24:27 +00:00
75aeb12e81 fix(lucene adapter and search tests): Improve range query parsing in Lucene adapter and expand search test coverage 2025-04-22 18:24:26 +00:00
c5a44da975 5.11.2
Some checks failed
Default (tags) / security (push) Successful in 38s
Default (tags) / test (push) Successful in 3m0s
Default (tags) / release (push) Failing after 52s
Default (tags) / metadata (push) Successful in 58s
2025-04-21 17:31:30 +00:00
969b073939 fix(readme): Update readme to clarify usage of searchable fields retrieval 2025-04-21 17:31:30 +00:00
7 changed files with 56 additions and 6 deletions

View File

@ -1,5 +1,19 @@
# Changelog
## 2025-04-22 - 5.11.3 - fix(lucene adapter and search tests)
Improve range query parsing in Lucene adapter and expand search test coverage
- Added a new 'testSearch' script in package.json to run search tests.
- Introduced advanced search tests for range queries and combined field filters in test/search.advanced.ts.
- Enhanced robustness tests in test/search.ts for wildcard and empty query scenarios.
- Fixed token validation in the parseRange method of the Lucene adapter to ensure proper error handling.
## 2025-04-21 - 5.11.2 - fix(readme)
Update readme to clarify usage of searchable fields retrieval
- Replaced getSearchableFields('Product') with Product.getSearchableFields()
- Updated documentation to reference the static method Class.getSearchableFields()
## 2025-04-21 - 5.11.1 - fix(doc)
Refactor searchable fields API and improve collection registration.

View File

@ -1,6 +1,6 @@
{
"name": "@push.rocks/smartdata",
"version": "5.11.1",
"version": "5.11.3",
"private": false,
"description": "An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.",
"main": "dist_ts/index.js",
@ -8,6 +8,7 @@
"type": "module",
"scripts": {
"test": "tstest test/",
"testSearch": "tsx test/test.search.ts",
"build": "tsbuild --web --allowimplicitany",
"buildDocs": "tsdoc"
},

View File

@ -203,7 +203,7 @@ class Product extends SmartDataDbDoc<Product, Product> {
}
// List searchable fields
const searchableFields = getSearchableFields('Product');
const searchableFields = Product.getSearchableFields();
// 1: Exact phrase across all fields
await Product.search('"Kindle Paperwhite"');
@ -230,7 +230,7 @@ await Product.search('');
The search functionality includes:
- `@searchable()` decorator for marking fields as searchable
- `getSearchableFields()` to list searchable fields for a model
- `Class.getSearchableFields()` static method to list searchable fields for a model
- `search(query: string)` method supporting:
- Exact phrase matches (`"my exact string"` or `'my exact string'`)
- Fieldscoped exact & wildcard searches (`field:value`, `field:Air*`)

View File

@ -172,6 +172,21 @@ tap.test('grouping: (Furniture OR Electronics) AND Chair', async () => {
expect(names).toEqual(['Gaming Chair', 'Office Chair']);
});
// Additional range and combined query tests
tap.test('range query price:[30 TO 300] returns expected products', async () => {
const res = await Product.search('price:[30 TO 300]');
// Expect products with price between 30 and 300 inclusive: Day Light Lamp, Gaming Chair, Office Chair, AirPods
expect(res.length).toEqual(4);
const names = res.map((r) => r.name).sort();
expect(names).toEqual(['AirPods', 'Day Light Lamp', 'Gaming Chair', 'Office Chair']);
});
tap.test('should filter category and price range', async () => {
const res = await Product.search('category:Lighting AND price:[30 TO 40]');
expect(res.length).toEqual(1);
expect(res[0].name).toEqual('Day Light Lamp');
});
// Teardown
tap.test('cleanup advanced search database', async () => {
await testDb.mongoDb.dropDatabase();

View File

@ -257,6 +257,26 @@ tap.test('should search hyphenated terms "E-reader"', async () => {
expect(ereaderResults[0].name).toEqual('Kindle Paperwhite');
});
// Additional robustness tests
tap.test('should return all products for empty search', async () => {
const searchResults = await Product.search('');
const allProducts = await Product.getInstances({});
expect(searchResults.length).toEqual(allProducts.length);
});
tap.test('should support wildcard plain term across all fields', async () => {
const results = await Product.search('*book*');
const names = results.map((r) => r.name).sort();
expect(names).toEqual(['Harry Potter', 'Kindle Paperwhite', 'MacBook Pro']);
});
tap.test('should support wildcard plain term with question mark pattern', async () => {
const results = await Product.search('?one?');
const names = results.map((r) => r.name).sort();
expect(names).toEqual(['Galaxy S21', 'iPhone 12']);
});
// Close database connection
tap.test('close database connection', async () => {
await testDb.mongoDb.dropDatabase();
await testDb.close();

View File

@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@push.rocks/smartdata',
version: '5.11.1',
version: '5.11.3',
description: 'An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.'
}

View File

@ -290,11 +290,11 @@ export class LuceneParser {
const includeLower = this.tokens[this.pos] === '[';
const includeUpper = this.tokens[this.pos + 4] === ']';
this.pos++; // Skip open bracket
// Ensure tokens for lower, TO, upper, and closing bracket exist
if (this.pos + 4 >= this.tokens.length) {
throw new Error('Invalid range query syntax');
}
this.pos++; // Skip open bracket
const lower = this.tokens[this.pos];
this.pos++;