{"id":26052418,"url":"https://github.com/vishwa-karthik/fuzzy_bolt","last_synced_at":"2026-04-11T09:01:41.590Z","repository":{"id":281233000,"uuid":"944639455","full_name":"Vishwa-Karthik/fuzzy_bolt","owner":"Vishwa-Karthik","description":"A powerful and optimized fuzzy search algorithm with typo tolerance and ranking in Dart","archived":false,"fork":false,"pushed_at":"2025-04-30T18:00:51.000Z","size":58,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-16T09:52:56.156Z","etag":null,"topics":["dart","dart-package","flutter","fuzzy-search","ranking-algorithm","search","search-algorithm","suggestions"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/fuzzy_bolt","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Vishwa-Karthik.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-07T17:48:00.000Z","updated_at":"2025-04-30T18:00:55.000Z","dependencies_parsed_at":"2025-04-30T19:32:59.214Z","dependency_job_id":null,"html_url":"https://github.com/Vishwa-Karthik/fuzzy_bolt","commit_stats":null,"previous_names":["vishwa-karthik/fuzzy_bolt"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Vishwa-Karthik/fuzzy_bolt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vishwa-Karthik%2Ffuzzy_bolt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vishwa-Karthik%2Ffuzzy_bolt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vishwa-Karthik%2Ffuzzy_bolt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vishwa-Karthik%2Ffuzzy_bolt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Vishwa-Karthik","download_url":"https://codeload.github.com/Vishwa-Karthik/fuzzy_bolt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vishwa-Karthik%2Ffuzzy_bolt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31674624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-11T08:18:19.405Z","status":"ssl_error","status_checked_at":"2026-04-11T08:17:08.892Z","response_time":54,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","dart-package","flutter","fuzzy-search","ranking-algorithm","search","search-algorithm","suggestions"],"created_at":"2025-03-08T06:33:44.351Z","updated_at":"2026-04-11T09:01:41.549Z","avatar_url":"https://github.com/Vishwa-Karthik.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fuzzy Bolt\r\n\r\n**An advanced Fuzzy Search Algorithm with intelligent typo correction, adaptive ranking, porter stemming and lightning-fast performance.**\r\n\r\n[![pub package](https://img.shields.io/pub/v/fuzzy_bolt.svg)](https://pub.dev/packages/fuzzy_bolt)\r\n[![License: BSD-3-Clause](https://img.shields.io/badge/license-BSD--3--Clause-blue)](LICENSE)\r\n\r\n## Why Fuzzy Bolt ??\r\n*I’ve explored several fuzzy search packages, but haven’t found one that intelligently corrects typos in queries and performs stemming on the dataset while searching*\r\n\r\n+ Uses [Jaro–Winkler Distance](https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance) for ranking the results.\r\n+ Uses [Levenshtein Distance](https://en.wikipedia.org/wiki/Levenshtein_distance) to handle the typo errors in the query if any.\r\n+ Uses [Porter Stemming](https://cloud.google.com/discover/what-is-stemming) process to intelligently search against the dataset.\r\n+ Leverage host's [Isolate](https://dart.dev/language/isolates) mechanism if the dataset becomes huge.\r\n+ Allow developers to switch to non-isolate mechanim for Web platform - Since Isolate do not work on them.\r\n+ Allow developers to set their threshold on results for better accuracy.\r\n\r\n## Use Case Applications\r\n\r\n- **Local Database Search**:\r\nPerfect for running fuzzy queries directly on local datasets like SQLite, Hive, or Isar.\r\n\r\n- **Post-API Result Search**:\r\nEnhance your UX by adding an extra layer of fuzzy search after fetching data from remote APIs.\r\n\r\n- **In-Memory State Search**:\r\nGreat for filtering and ranking results from app state (e.g in-memory lists, BLoC/Cubit states, Provider data, etc.).\r\n\r\n- **Search Bars \u0026 Autocomplete Fields**:\r\nSupercharge your TextField or SearchDelegate with typo-tolerant and intent-aware results.\r\n\r\n- **Offline-First Applications**:\r\nHelpful in apps that prioritize offline functionality and require local, fast search.\r\n\r\n- **Data Cleaning \u0026 Record Linking**:\r\nUse it for fuzzy matching and deduplication tasks (e.g., merging similar records in datasets).\r\n\r\n- **Command Palette / Quick Actions Search**:\r\nPerfect for developer tools or admin dashboards where users trigger commands via text input.\r\n\r\n## 📦 Installation\r\n\r\nAdd Fuzzy Bolt to your project:\r\n\r\n```yaml\r\ndependencies:\r\n  fuzzy_bolt: \u003clatest-version\u003e\r\n```\r\n\r\nThen grab it:\r\n\r\n```bash\r\ndart pub get  # or flutter pub get\r\n```\r\n\r\n---\r\n\r\n## 🚀 Quick Start\r\n\r\nHere's the simplest way to get started:\r\n\r\n```dart\r\nimport 'package:fuzzy_bolt/fuzzy_bolt.dart';\r\n\r\nfinal users = [\r\n  User(name: 'Alice Johnson', email: 'alice@example.com'),\r\n  User(name: 'Bob Smith', email: 'bob@example.com'),\r\n];\r\n\r\n// Basic search - just give me the matching items\r\nfinal results = await FuzzyBolt.search\u003cUser\u003e(\r\n  users,\r\n  'Alise',  // Yep, typo tolerance built-in!\r\n  selectors: [(u) =\u003e u.name],\r\n);\r\n\r\n// Want to see how confident each match is?\r\nfinal scored = await FuzzyBolt.searchWithScores\u003cUser\u003e(\r\n  users,\r\n  'alice',\r\n  selectors: [(u) =\u003e u.name],\r\n);\r\n\r\nfor (final result in scored) {\r\n  print('${result.item.name}: ${(result.score * 100).toInt()}% match');\r\n  // Output: Alice Johnson: 100% match\r\n}\r\n```\r\n\r\n## 📖 Complete API Guide\r\n\r\n### 1. Basic Search → `FuzzyBolt.search()`\r\n\r\n**When to use:** You just want the matching items, no extra details needed.\r\n\r\n```dart\r\nFuture\u003cList\u003cT\u003e\u003e FuzzyBolt.search\u003cT\u003e(\r\n  List\u003cT\u003e dataset,\r\n  String query,\r\n  {\r\n    required List\u003cString Function(T)\u003e selectors,  // Tell it which fields to search\r\n    double strictThreshold = 0.85,     // How strict for exact matches (0.0-1.0)\r\n    double typeThreshold = 0.65,       // How forgiving for typos (0.0-1.0)\r\n    int? maxResults,                   // Cap the results\r\n    bool skipIsolate = false,          // Set true for web\r\n  }\r\n)\r\n```\r\n\r\n**Real examples:**\r\n\r\n```dart\r\n// Simple name search\r\nfinal results = await FuzzyBolt.search\u003cUser\u003e(\r\n  users,\r\n  'alice',\r\n  selectors: [(u) =\u003e u.name],\r\n);\r\n\r\n// Search across multiple fields (name, email, department, etc.)\r\nfinal results = await FuzzyBolt.search\u003cProduct\u003e(\r\n  products,\r\n  'running shoes',\r\n  selectors: [(p) =\u003e p.name, (p) =\u003e p.description, (p) =\u003e p.category],\r\n);\r\n\r\n// Just give me the top 5 results\r\nfinal top5 = await FuzzyBolt.search\u003cUser\u003e(\r\n  users,\r\n  'john',\r\n  selectors: [(u) =\u003e u.name],\r\n  maxResults: 5,\r\n);\r\n```\r\n\r\n---\r\n\r\n### 2. Search With Scores → `FuzzyBolt.searchWithScores()`\r\n\r\n**When to use:** You need to show users how confident each match is, or rank results.\r\n\r\n```dart\r\nFuture\u003cList\u003cFuzzyResult\u003cT\u003e\u003e\u003e FuzzyBolt.searchWithScores\u003cT\u003e(\r\n  List\u003cT\u003e dataset,\r\n  String query,\r\n  {\r\n    required List\u003cString Function(T)\u003e selectors,\r\n    double strictThreshold = 0.85,\r\n    double typeThreshold = 0.65,\r\n    int? maxResults,\r\n  }\r\n)\r\n```\r\n\r\n**What you get back:**\r\n\r\n```dart\r\nclass FuzzyResult\u003cT\u003e {\r\n  final T item;              // Your original item\r\n  final double score;        // How well it matched: 0.0 (terrible) to 1.0 (perfect)\r\n  final String matchedText;  // The actual text that matched\r\n}\r\n```\r\n\r\n**Example:**\r\n\r\n```dart\r\nfinal results = await FuzzyBolt.searchWithScores\u003cProduct\u003e(\r\n  products,\r\n  'runing shos',  // Multiple typos? No problem!\r\n  selectors: [(p) =\u003e p.name],\r\n);\r\n\r\nfor (final result in results) {\r\n  final confidence = (result.score * 100).toStringAsFixed(1);\r\n  print('${result.item.name} - $confidence% match');\r\n}\r\n// Output:\r\n// Running Shoes Pro - 87.5% match\r\n// Walking Shoes - 65.2% match\r\n```\r\n\r\n---\r\n\r\n### 3. Search With Config → `FuzzyBolt.searchWithConfig()`\r\n\r\n**When to use:** You need fine-tuned control over how the search behaves.\r\n\r\n```dart\r\nfinal strictConfig = FuzzySearchConfig(\r\n  strictThreshold: 0.95,  // Very picky about matches\r\n  typeThreshold: 0.85,    // Don't be too forgiving with typos\r\n  maxResults: 10,\r\n);\r\n\r\nfinal results = await FuzzyBolt.searchWithConfig\u003cProduct\u003e(\r\n  products,\r\n  'iPhone 15',\r\n  [(p) =\u003e p.name],\r\n  strictConfig,\r\n);\r\n```\r\n\r\n---\r\n\r\n### 4. Text Processing Search → `FuzzyBolt.searchWithTextProcessing()`\r\n\r\n**When to use:** You need advanced text processing like stemming and stop word removal.\r\n\r\n```dart\r\nfinal results = await FuzzyBolt.searchWithTextProcessing\u003cArticle\u003e(\r\n  articles,\r\n  'the runners are running',\r\n  selectors: [(a) =\u003e a.title, (a) =\u003e a.content],\r\n  enableStemming: true,      // \"runners\" becomes \"runner\", \"running\" becomes \"run\"\r\n  removeStopWords: true,     // Removes \"the\", \"are\", etc.\r\n);\r\n```\r\n\r\n---\r\n\r\n### 5. Porter Stemmer → Direct Word Manipulation\r\n\r\n**When to use:** You need to stem words yourself for preprocessing or analysis.\r\n\r\n```dart\r\n// Stem individual words\r\nprint(PorterStemmer.stem('running'));  // \"run\"\r\nprint(PorterStemmer.stem('flies'));    // \"fli\"\r\nprint(PorterStemmer.stem('dogs'));     // \"dog\"\r\n\r\n// Process entire sentences\r\nfinal text = 'The runners were running quickly';\r\nprint(PorterStemmer.stemText(text));   // \"runner were run quickli\"\r\n\r\n// Check the stop words list (77 common English words)\r\nprint(PorterStemmer.stopWords.contains('the'));  // true\r\n```\r\n\r\n---\r\n\r\n### 6. Dataset Cleaning → `StandardDatasetCleaner`\r\n\r\n**When to use:** Your data has duplicates or low-quality entries you want to filter out before searching.\r\n\r\n```dart\r\n// Pick a cleaning strategy\r\nfinal cleaner = StandardDatasetCleaner.minimal\u003cProduct\u003e();        // Gentle cleaning\r\nfinal cleaner = StandardDatasetCleaner.forEcommerce\u003cProduct\u003e();   // Balanced (recommended)\r\nfinal cleaner = StandardDatasetCleaner.aggressive\u003cProduct\u003e();     // Maximum cleaning\r\n\r\n// Clean your dataset\r\nfinal result = cleaner.cleanDataset(\r\n  products,\r\n  [(p) =\u003e p.name],\r\n  qualityThreshold: 0.3,\r\n  removeDuplicates: true,\r\n);\r\n\r\nprint('Original: ${result.statistics.originalCount}');\r\nprint('Cleaned: ${result.statistics.cleanedCount}');\r\nprint('Removed: ${result.statistics.duplicatesRemoved} duplicates');\r\n\r\n// Now search the cleaned data\r\nfinal searchResults = await FuzzyBolt.search\u003cProduct\u003e(\r\n  result.cleanedItems,  // Use the cleaned list\r\n  'running shoes',\r\n  selectors: [(p) =\u003e p.name],\r\n);\r\n```\r\n\r\n---\r\n\r\n### 7. Cache Management\r\n\r\n```dart\r\n// Clear the internal text processing cache\r\nFuzzyBolt.clearTextCache();\r\n\r\n// Check cache stats\r\nfinal stats = FuzzyBolt.getTextCacheStats();\r\nprint('Cache has ${stats[\"cacheSize\"]} items (max: ${stats[\"maxCacheSize\"]})');\r\n```\r\n\r\n---\r\n\r\n## 💡 Real-World Use Cases\r\n\r\n**E-commerce: Product search with typos**\r\n\r\n```dart\r\nfinal results = await FuzzyBolt.searchWithScores\u003cProduct\u003e(\r\n  products,\r\n  'runing shos',  // User can't spell? We got you.\r\n  selectors: [(p) =\u003e p.name, (p) =\u003e p.description],\r\n);\r\n```\r\n\r\n**HR/Directory: Find employees across departments**\r\n\r\n```dart\r\nfinal results = await FuzzyBolt.search\u003cEmployee\u003e(\r\n  employees,\r\n  'john engineering',\r\n  selectors: [(e) =\u003e e.name, (e) =\u003e e.department, (e) =\u003e e.title],\r\n);\r\n```\r\n\r\n**Content/Docs: Smart document search**\r\n\r\n```dart\r\nfinal results = await FuzzyBolt.searchWithTextProcessing\u003cDocument\u003e(\r\n  docs,\r\n  'professional runners training',\r\n  selectors: [(d) =\u003e d.title, (d) =\u003e d.content],\r\n  enableStemming: true,\r\n  removeStopWords: true,\r\n);\r\n```\r\n\r\n**Big Data: Search through 10,000+ items**\r\n\r\n```dart\r\nfinal results = await FuzzyBolt.search\u003cUser\u003e(\r\n  massiveUserList,  // 10,000+ users\r\n  'alice',\r\n  selectors: [(u) =\u003e u.name],\r\n  maxResults: 10,  // Get top 10 only\r\n);\r\n// Automatically uses parallel processing—no config needed!\r\n```\r\n\r\n---\r\n\r\n## ⚡ Performance Tips\r\n\r\n**Pro tip #1:** Limit your results if you don't need everything\r\n\r\n```dart\r\nmaxResults: 10  // Stop after finding 10 matches\r\n```\r\n\r\n**Pro tip #2:** Lower the isolate threshold for better performance on medium datasets\r\n\r\n```dart\r\nisolateThreshold: 500  // Use parallel processing at 500+ items (default: 1000)\r\n```\r\n\r\n**Pro tip #3:** Turn off features you don't need\r\n\r\n```dart\r\nenableStemming: false    // Skip if you don't need word variation matching\r\nenableCleaning: false    // Skip if your data is already clean\r\n```\r\n\r\n**Pro tip #4:** Clean once, search many times\r\n\r\n```dart\r\n// Clean your dataset once\r\nfinal cleaned = cleaner.cleanDataset(products, [(p) =\u003e p.name]);\r\n\r\n// Then reuse the cleaned data for multiple searches\r\nfor (final query in userQueries) {\r\n  final results = await FuzzyBolt.search\u003cProduct\u003e(\r\n    cleaned.cleanedItems,  // Already clean!\r\n    query,\r\n    selectors: [(p) =\u003e p.name],\r\n    enableCleaning: false,  // No need to clean again\r\n  );\r\n}\r\n```\r\n\r\n**What to expect:**\r\n\r\n| Dataset Size       | Parallel Processing? | Typical Time |\r\n| ------------------ | -------------------- | ------------ |\r\n| Under 100 items    | Nope                 | \u003c 10ms       |\r\n| 100-1,000 items    | Nope                 | 10-100ms     |\r\n| 1,000-10,000 items | Yes (automatic)      | 100ms-1s     |\r\n| 10,000+ items      | Yes (automatic)      | 1-3s         |\r\n\r\n---\r\n\r\n## 🌐 Web Platform Note\r\n\r\n**Heads up:** Isolates aren't available on web. Just set `skipIsolate: true`:\r\n\r\n```dart\r\nimport 'package:flutter/foundation.dart' show kIsWeb;\r\n\r\nfinal results = await FuzzyBolt.search\u003cUser\u003e(\r\n  users,\r\n  'query',\r\n  selectors: [(u) =\u003e u.name],\r\n  skipIsolate: kIsWeb,  // Handles web automatically\r\n);\r\n```\r\n\r\n---\r\n\r\n## 🎛️ Understanding Thresholds\r\n\r\nThink of thresholds like \"how picky should the search be?\"\r\n\r\n**strictThreshold (default: 0.85)**\r\n\r\n- **Higher** (like 0.95) = Be very picky, only near-perfect matches\r\n- **Lower** (like 0.7) = Be more chill, allow more variation\r\n\r\n```dart\r\nstrictThreshold: 0.95  // \"Alice\" matches \"Alice\" only\r\nstrictThreshold: 0.85  // \"Alice\" matches \"Alice\" and \"Alicia\"\r\nstrictThreshold: 0.7   // \"Alice\" matches \"Alice\", \"Alicia\", \"Alise\"\r\n```\r\n\r\n**typeThreshold (default: 0.65)**\r\n\r\n- **Higher** (like 0.85) = Strict typo checking\r\n- **Lower** (like 0.4) = Very forgiving with typos\r\n\r\n```dart\r\ntypeThreshold: 0.85  // \"Alise\" might not match \"Alice\"\r\ntypeThreshold: 0.65  // \"Alise\" matches \"Alice\" ✓\r\ntypeThreshold: 0.4   // \"Alce\" matches \"Alice\" ✓\r\n```\r\n\r\n---\r\n\r\n## 📱 Platform Support\r\n\r\nWorks everywhere Dart works:\r\n\r\n| Platform | Status | Notes                      |\r\n| -------- | ------ | -------------------------- |\r\n| Android  | ✅     | Full support with isolates |\r\n| iOS      | ✅     | Full support with isolates |\r\n| macOS    | ✅     | Full support with isolates |\r\n| Windows  | ✅     | Full support with isolates |\r\n| Linux    | ✅     | Full support with isolates |\r\n| Web      | ✅     | Use `skipIsolate: true`    |\r\n\r\n---\r\n\r\n## 🧪 Testing \u0026 Quality\r\n\r\n**87 comprehensive tests** covering:\r\n\r\n- Basic search \u0026 typo tolerance\r\n- Multi-field search\r\n- Large datasets (10,000+ items)\r\n- Text processing \u0026 stemming\r\n- Dataset cleaning\r\n- Edge cases (unicode, empty strings, special characters)\r\n- Concurrent access \u0026 memory efficiency\r\n\r\nRun tests yourself:\r\n\r\n```bash\r\ndart test\r\n```\r\n\r\n---\r\n\r\n## 📄 License\r\n\r\nBSD-3-Clause License – Free to use, even commercially. See [LICENSE](LICENSE) for details.\r\n\r\n---\r\n\r\n## 🤝 Need Help?\r\n\r\n- 🐛 Found a bug? [Report it here](https://github.com/Vishwa-Karthik/fuzzy_bolt/issues)\r\n- 💬 Have questions? [Start a discussion](https://github.com/Vishwa-Karthik/fuzzy_bolt/discussions)\r\n- ⭐ Like it? Give us a star on GitHub!\r\n\r\n---\r\n\r\n**Built with ❤️ for Dart Community**\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvishwa-karthik%2Ffuzzy_bolt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvishwa-karthik%2Ffuzzy_bolt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvishwa-karthik%2Ffuzzy_bolt/lists"}