feat(search): Improve search functionality: update documentation, refine Lucene query transformation, and add advanced search tests

This commit is contained in:
2025-04-21 15:27:55 +00:00
parent 0834ec5c91
commit 23b499b3a8
7 changed files with 373 additions and 76 deletions

View File

@@ -189,48 +189,42 @@ await user.delete(); // Delete the user from the database
### Search Functionality
SmartData provides powerful search capabilities with a Lucene-like query syntax and robust fallback mechanisms:
SmartData provides powerful, Lucenestyle search capabilities with robust fallback mechanisms:
```typescript
// Define a model with searchable fields
@Collection(() => db)
class Product extends SmartDataDbDoc<Product, Product> {
@unI()
public id: string = 'product-id';
@svDb()
@searchable() // Mark this field as searchable
public name: string;
@svDb()
@searchable() // Mark this field as searchable
public description: string;
@svDb()
@searchable() // Mark this field as searchable
public category: string;
@svDb()
public price: number;
@unI() public id: string = 'product-id';
@svDb() @searchable() public name: string;
@svDb() @searchable() public description: string;
@svDb() @searchable() public category: string;
@svDb() public price: number;
}
// Get all fields marked as searchable for a class
const searchableFields = getSearchableFields('Product'); // ['name', 'description', 'category']
// List searchable fields
const searchableFields = getSearchableFields('Product');
// Basic search across all searchable fields
const iphoneProducts = await Product.search('iPhone');
// 1: Exact phrase across all fields
await Product.search('"Kindle Paperwhite"');
// Field-specific exact match
const electronicsProducts = await Product.search('category:Electronics');
// 2: Wildcard search across all fields
await Product.search('Air*');
// Partial word search (regex across all fields)
const laptopResults = await Product.search('laptop');
// 3: Fieldscoped wildcard
await Product.search('name:Air*');
// Multi-word literal search
const paperwhite = await Product.search('Kindle Paperwhite');
// 4: Boolean AND/OR/NOT
await Product.search('category:Electronics AND name:iPhone');
// Empty query returns all documents
const allProducts = await Product.search('');
// 5: Grouping with parentheses
await Product.search('(Furniture OR Electronics) AND Chair');
// 6: Multiterm unquoted (terms ANDd across fields)
await Product.search('TypeScript Aufgabe');
// 7: Empty query returns all documents
await Product.search('');
```
The search functionality includes:
@@ -238,11 +232,14 @@ The search functionality includes:
- `@searchable()` decorator for marking fields as searchable
- `getSearchableFields()` to list searchable fields for a model
- `search(query: string)` method supporting:
- Field-specific exact matches (`field:value`)
- Case-insensitive partial matches across all searchable fields
- Multi-word literal matching
- Exact phrase matches (`"my exact string"` or `'my exact string'`)
- Fieldscoped exact & wildcard searches (`field:value`, `field:Air*`)
- Wildcard searches across all fields (`Air*`, `?Pods`)
- Boolean operators (`AND`, `OR`, `NOT`) with grouping (`(...)`)
- Multiterm unquoted queries ANDd across fields (`TypeScript Aufgabe`)
- Single/multiterm regex searches across fields
- Empty queries returning all documents
- Automatic escaping of special characters to prevent regex injection
- Automatic escaping & wildcard conversion to prevent regex injection
### EasyStore