A lightweight, powerful object search engine for JavaScript with advanced query syntax.
npm install @ecromaneli/search-engine- Powerful query language with boolean operators (AND/OR)
- Field-specific searches
- Support for wildcards and regex pattern matching
- Numeric range searches
- Logical negation of search terms
- Nested property searching
- Logical grouping with parentheses
- Customizable search options
- Zero dependencies
constSearchEngine=require('@ecromaneli/search-engine')constusers=[{id: 1,name: 'John Doe',age: 28,tags: ['developer','javascript']},{id: 2,name: 'Jane Smith',age: 34,tags: ['designer','ui/ux']},{id: 3,name: 'Bob Johnson',age: 45,tags: ['manager','finance']}]constresult=SearchEngine.search(users,'name: john')console.log(result)You can create a SearchEngine instance with specific options that will be used for all searches:
constengine=newSearchEngine({excludeKeys: ['name','tags'],allowNumericString: false,allowKeyValueMatching: true,matchChildKeysAsValues: false,maxLevels: 5})constresults=engine.search(users,'age~: 25-35')console.log(results)The SearchOptions object allows you to customize the behavior of the search engine. Below is a table explaining each option:
| Option | Type | Default | Description |
|---|---|---|---|
excludeKeys | string[] | [] | Array of keys to exclude from search. Useful for excluding sensitive data. |
allowNumericString | boolean | true | Controls whether string values that can be parsed as numbers are used in range searches. |
allowKeyValueMatching | boolean | true | When enabled, unquoted terms without a field/value separator match both field names and values. |
matchChildKeysAsValues | boolean | false | When enabled, after finding a matching key, also looks for the value in child object keys. |
maxLevels | number | unlimited | Maximum levels of nested objects to search through. Useful to avoid infinite loops in deeply nested or circular data. |
- The
maxLevelsoption can be set to limit how deep the search will go into nested objects. This is especially useful for large or circular data structures.
allowNumericString:- When
true, strings like"123"will be treated as numbers in range searches. - When
false, only actual numbers will be considered for range searches.
- When
allowKeyValueMatching:- When
true, a query likeadminwill match both{ admin: "value" }and{ key: "admin" }. - When
false, it will only match field names or values explicitly.
- When
matchChildKeysAsValues:- When
true, a query likefoo:barwill match both{ foo: "bar" }and{foo: { bar: "value" }}. - When
false, it will only match{ foo: "bar" }.
- When
foo- Search for objects having a field or valuefoo."value"- Search for"value"in any field.field: value- Search forvaluein the specificfield.
field*: pattern- Regex pattern match on field.field~: min-max- Numeric range search.field~: 10-- Numbers greater than or equal to 10.field~: -20- Numbers less than or equal to 20.
field is value- Search for objects wherefieldis exactlyvalue.field is not value- Search for objects wherefieldis notvalue.
Where value must be one of the following:
- A boolean (
trueorfalse) nullundefined(orundef)blank(empty strings)empty(empty arrays)
term1 and term2- Both terms must match.term1 or term2- Either term must match.
not term- Term must not match.not (term1 or term2)- Group negation (neither term1 nor term2 should match).(term1 or term2) and term3- Logical grouping with parentheses.
objList(Array): Array of objects to search through.queryStr(String): Query string following the syntax described above.options(Object, optional): Search options object.- Returns (
Array): Array of matching objects.
To store the options, use the constructor below:
options(Object, optional): Search options object (see Options table).- Returns (
SearchEngine): A newSearchEngineinstance with the specified options.
objList(Array): Array of objects to search through.queryStr(String): Query string following the syntax described above.- Returns (
Array): Array of matching objects with the instance's options applied.
- For large datasets, consider disabling
allowNumericStringif you don't need string-to-number conversion. - Set
matchChildKeysAsValues: false(default) unless you specifically need to match object keys as values. - Use
excludeKeysto skip searching in fields that are never relevant to your searches. - For repeated searches with the same options, create a
SearchEngineinstance instead of using the static method. - Limit
maxLevelsif you have deeply nested data to avoid performance issues.
For a comprehensive set of usage examples covering all search engine features, refer to our test suite:
The test file includes examples of:
- Complex nested property searching
- Array item searching
- Logical grouping with parentheses
- De Morgan's law transformations
- Complex boolean expressions
- Excluded keys functionality
- Range searches with various configurations
- Quoted values with special characters
- Edge cases and error handling
These examples serve as excellent reference implementations when building advanced search queries.
Created by Emerson Capuchi Romaneli (@ECRomaneli).
This project is licensed under the MIT License.