Search Engine
Fast and lightweight search engine for Dart/Flutter with fuzzy search capabilities β lightweight and flexible.
π Live Demo:** View on GitHub Pages
How Search Works
The search engine uses a weighted relevance algorithm to find the most relevant results:
1. Search Priorities (in order of importance)
- Exact matches -
"apple"="apple" - Starts with -
"app"β"apple" - Contains -
"ple"β"apple" - Fuzzy search fallback -
"aple"β"apple"(only infuzzySearch)
2. Search Fields
By default, search looks in 3 fields:
name- item namesubtitle- item subtitlesearchData- additional search data
3. Character Types
Search works with any characters:
- β
Letters:
"apple","Π―Π±Π»ΠΎΠΊΠΎ" - β
Numbers:
"iPhone 14","Windows 11" - β
Special characters:
"C++","React.js" - β
Emojis:
"π Apple" - β
Spaces:
"Red fruit"
4. Weighted Relevance
This is one scoring pipeline, not separate searches:
- Exact field match gets the highest score.
- Prefix and word-boundary matches get strong scores.
- Contains/token matches get medium scores.
- Fuzzy typo correction gets fallback scores.
Field weights are applied (name > subtitle > searchData by default), then results are sorted by score.
Features
- π Fast search by name, subtitle, or custom fields
- π― Fuzzy search for typos and misspellings
- β‘ Reusable index for fast repeated queries
- π Weighted scoring for better result quality
- π¨ Configurable search behavior
- π¦ Zero dependencies - pure Dart implementation
Installation
Add this to your package's pubspec.yaml file:
dependencies:
fuzzy_search_engine: ^1.1.0
Quick Start
import 'package:fuzzy_search_engine/fuzzy_search_engine.dart';
void main() {
final items = [
SearchableItem(id: '1', name: 'Apple', subtitle: 'Red fruit'),
SearchableItem(id: '2', name: 'Banana', subtitle: 'Yellow fruit'),
SearchableItem(id: '3', name: 'Orange', subtitle: 'Orange fruit'),
];
// Basic search
final results = SearchEngine.search(items, 'apple');
print(results); // [Apple]
// Fuzzy search for typos
final fuzzyResults = SearchEngine.fuzzySearch(items, 'aple');
print(fuzzyResults); // [Apple]
}
API Reference
SearchableItem
Represents a searchable item with customizable fields.
const item = SearchableItem(
id: '1',
name: 'Apple',
icon: 'π',
subtitle: 'Red fruit',
searchData: 'apple fruit red',
data: {'price': 1.99},
);
SearchEngine
Main search engine class with static methods.
Basic Search
// Search with default configuration
List<SearchableItem> results = SearchEngine.search(items, query);
// Search with custom configuration
List<SearchableItem> results = SearchEngine.search(
items,
query,
config: SearchConfig(
searchFields: ['name', 'subtitle'],
caseSensitive: false,
// You can enable debug logs in Flutter apps using debugPrint
// debugLogger: debugPrint,
),
);
Fuzzy Search
// Fuzzy search for typos and misspellings
List<SearchableItem> results = SearchEngine.fuzzySearch(items, query);
// Fuzzy search with custom configuration
List<SearchableItem> results = SearchEngine.fuzzySearch(
items,
query,
config: SearchConfig(
fuzzyEnabled: true,
maxFuzzyDistance: 3,
// debugLogger: debugPrint,
),
);
Reusable Index (for best performance)
final index = SearchEngine.buildIndex(
items,
config: const SearchConfig(maxResults: 20),
);
final first = index.search('apple');
final second = index.fuzzySearch('aple');
Utility Methods
// Sort items by name
List<SearchableItem> sorted = SearchEngine.getSortedItems(items);
// Find item by ID
SearchableItem? item = SearchEngine.getItemById(items, 'item_id');
SearchConfig
Configuration for search behavior.
const config = SearchConfig(
searchFields: ['name', 'subtitle', 'searchData'], // Fields to search in
fuzzyEnabled: true, // Enable fuzzy search
maxFuzzyDistance: 3, // Max distance for fuzzy search
caseSensitive: false, // Case sensitive search
maxResults: 20, // Optional result limit
fieldWeights: { // Optional per-field scoring weight
'name': 1.0,
'subtitle': 0.85,
'searchData': 0.75,
},
);
Search Algorithm
The search engine uses a score-based algorithm:
- Exact matches - Highest priority
- Starts-with and word-boundary matches - High priority
- Contains matches - Third priority
- Fuzzy matches - Fallback (only in fuzzy search)
Fuzzy Search
Fuzzy search uses a bounded Damerau-Levenshtein distance (supports adjacent transpositions, e.g. oragne β orange) and adaptive thresholds for better speed and quality.
Examples
Basic Usage
final countries = [
SearchableItem(id: 'us', name: 'United States', subtitle: 'North America'),
SearchableItem(id: 'uk', name: 'United Kingdom', subtitle: 'Europe'),
SearchableItem(id: 'ca', name: 'Canada', subtitle: 'North America'),
];
// Search by name
final results = SearchEngine.search(countries, 'united');
// Returns: [United States, United Kingdom]
// Search by subtitle
final results = SearchEngine.search(countries, 'europe');
// Returns: [United Kingdom]
Advanced Configuration
final config = SearchConfig(
searchFields: ['name'], // Only search in name field
caseSensitive: true, // Case sensitive search
fuzzyEnabled: false, // Disable fuzzy search
);
final results = SearchEngine.search(countries, 'UNITED', config: config);
// Returns: [] (no exact match for 'UNITED')
Fuzzy Search Examples
final fruits = [
SearchableItem(id: '1', name: 'Apple'),
SearchableItem(id: '2', name: 'Banana'),
SearchableItem(id: '3', name: 'Orange'),
];
// Find items with typos
SearchEngine.fuzzySearch(fruits, 'aple'); // Returns: [Apple]
SearchEngine.fuzzySearch(fruits, 'bananna'); // Returns: [Banana]
SearchEngine.fuzzySearch(fruits, 'oragne'); // Returns: [Orange]
Performance
- Best practice: build
SearchIndexonce and reuse it for repeated queries - Candidate pruning: token/prefix maps reduce work for large datasets
- Fuzzy optimization: bounded distance with early stop avoids full DP work when mismatch is obvious
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License.
Libraries
- fuzzy_search_engine
- A Dart package for fast and lightweight search with fuzzy search capabilities.