Fast and lightweight search engine for Dart/Flutter with fuzzy search capabilities β lightweight and flexible.
π Live Demo:** View on GitHub Pages
The search engine uses a 4-level priority algorithm to find the most relevant results:
- Exact matches -
"apple"
="apple"
- Starts with -
"app"
β"apple"
- Contains -
"ple"
β"apple"
- Fuzzy search -
"aple"
β"apple"
(only for queries β₯3 characters)
By default, search looks in 3 fields:
name
- item namesubtitle
- item subtitlesearchData
- additional search data
Search works with any characters:
- β
Letters:
"apple"
,"Π―Π±Π»ΠΎΠΊΠΎ"
- β
Numbers:
"iPhone 14"
,"Windows 11"
- β
Special characters:
"C++"
,"React.js"
- β
Emojis:
"π Apple"
- β
Spaces:
"Red fruit"
This is one smart algorithm, not 4 different searches:
- Exact - for quick exact match finding (100% relevance)
- Starts with - for autocomplete (user types beginning) (90% relevance)
- Contains - for partial word search (70% relevance)
- Fuzzy - for typo correction (50% relevance)
Results are sorted by priority - exact matches first, then others.
- π Fast search by name, subtitle, or custom fields
- π― Fuzzy search for typos and misspellings
- β‘ Optimized performance with priority-based results
- π¨ Configurable search behavior
- π¦ Zero dependencies - pure Dart implementation
Add this to your package's pubspec.yaml
file:
dependencies:
fuzzy_search_engine: ^1.0.1
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]
}
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},
);
Main search engine class with static methods.
// 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 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,
),
);
// Sort items by name
List<SearchableItem> sorted = SearchEngine.getSortedItems(items);
// Find item by ID
SearchableItem? item = SearchEngine.getItemById(items, 'item_id');
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
);
The search engine uses a priority-based algorithm:
- Exact matches - Highest priority
- Starts with matches - Second priority
- Contains matches - Third priority
- Fuzzy matches - Lowest priority (only in fuzzy search)
Fuzzy search uses the Levenshtein distance algorithm to find items with typos and misspellings. It automatically adjusts the distance threshold based on query length for optimal results.
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]
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')
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]
- Time Complexity: O(n * m) where n is number of items, m is average field length
- Space Complexity: O(n) for storing results
- Memory: Minimal memory footprint with no external dependencies
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.