{"id":13408192,"url":"https://github.com/lucaong/minisearch","last_synced_at":"2025-04-23T20:56:23.660Z","repository":{"id":37678070,"uuid":"149144662","full_name":"lucaong/minisearch","owner":"lucaong","description":"Tiny and powerful JavaScript full-text search engine for browser and Node","archived":false,"fork":false,"pushed_at":"2025-02-19T13:14:34.000Z","size":5544,"stargazers_count":5222,"open_issues_count":7,"forks_count":144,"subscribers_count":31,"default_branch":"master","last_synced_at":"2025-04-23T20:56:04.905Z","etag":null,"topics":["autocomplete","autosuggestion","edge-computing","fulltext-search","fuzzy-search","javascript","search","search-engine","text-search","typo-tolerance"],"latest_commit_sha":null,"homepage":"https://lucaong.github.io/minisearch/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lucaong.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","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}},"created_at":"2018-09-17T15:13:16.000Z","updated_at":"2025-04-23T12:34:38.000Z","dependencies_parsed_at":"2023-12-28T00:24:13.516Z","dependency_job_id":"9e8535f8-4429-456c-b199-36967d3f3bba","html_url":"https://github.com/lucaong/minisearch","commit_stats":{"total_commits":633,"total_committers":20,"mean_commits":31.65,"dds":"0.45023696682464454","last_synced_commit":"325dbd8b10e1f985163b81874f146084527e9f00"},"previous_names":[],"tags_count":80,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucaong%2Fminisearch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucaong%2Fminisearch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucaong%2Fminisearch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucaong%2Fminisearch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lucaong","download_url":"https://codeload.github.com/lucaong/minisearch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250514767,"owners_count":21443208,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["autocomplete","autosuggestion","edge-computing","fulltext-search","fuzzy-search","javascript","search","search-engine","text-search","typo-tolerance"],"created_at":"2024-07-30T20:00:51.328Z","updated_at":"2025-04-23T20:56:23.641Z","avatar_url":"https://github.com/lucaong.png","language":"TypeScript","readme":"# MiniSearch\n\n[![CI Build](https://github.com/lucaong/minisearch/workflows/CI%20Build/badge.svg)](https://github.com/lucaong/minisearch/actions)\n[![Coverage Status](https://coveralls.io/repos/github/lucaong/minisearch/badge.svg?branch=master)](https://coveralls.io/github/lucaong/minisearch?branch=master)\n[![Minzipped Size](https://badgen.net/bundlephobia/minzip/minisearch)](https://bundlephobia.com/result?p=minisearch)\n[![npm](https://img.shields.io/npm/v/minisearch?color=%23ff00dd)](https://www.npmjs.com/package/minisearch)\n[![npm downloads](https://img.shields.io/npm/dw/minisearch)](https://www.npmjs.com/package/minisearch)\n[![types](https://img.shields.io/npm/types/minisearch)](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html)\n\n`MiniSearch` is a tiny but powerful in-memory fulltext search engine written in\nJavaScript. It is respectful of resources, and it can comfortably run both in\nNode and in the browser.\n\nTry out the [demo application](https://lucaong.github.io/minisearch/demo/).\n\nFind the complete [documentation and API reference\nhere](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html),\nand more background about `MiniSearch`, including a comparison with other\nsimilar libraries, in [this blog\npost](https://lucaongaro.eu/blog/2019/01/30/minisearch-client-side-fulltext-search-engine.html).\n\n`MiniSearch` follows [semantic versioning](https://semver.org/spec/v2.0.0.html),\nand documents releases and changes in the\n[changelog](https://github.com/lucaong/minisearch/blob/master/CHANGELOG.md).\n\n\n## Use case\n\n`MiniSearch` addresses use cases where full-text search features are needed\n(e.g. prefix search, fuzzy search, ranking, boosting of fields…), but the data\nto be indexed can fit locally in the process memory. While you won't index the\nwhole Internet with it, there are surprisingly many use cases that are served\nwell by `MiniSearch`. By storing the index in local memory, `MiniSearch` can\nwork offline, and can process queries quickly, without network latency.\n\nA prominent use-case is real time search \"as you type\" in web and mobile\napplications, where keeping the index on the client enables fast and reactive\nUIs, removing the need to make requests to a search server.\n\n\n## Features\n\n  * Memory-efficient index, designed to support memory-constrained use cases\n    like mobile browsers.\n\n  * Exact match, prefix search, fuzzy match, field boosting.\n\n  * Auto-suggestion engine, for auto-completion of search queries.\n\n  * Modern search result ranking algorithm.\n\n  * Documents can be added and removed from the index at any time.\n\n  * Zero external dependencies.\n\n`MiniSearch` strives to expose a simple API that provides the building blocks to\nbuild custom solutions, while keeping a small and well tested codebase.\n\n\n## Installation\n\nWith `npm`:\n\n```\nnpm install minisearch\n```\n\nWith `yarn`:\n\n```\nyarn add minisearch\n```\n\nThen `require` or `import` it in your project:\n\n```javascript\n// If you are using import:\nimport MiniSearch from 'minisearch'\n\n// If you are using require:\nconst MiniSearch = require('minisearch')\n```\n\nAlternatively, if you prefer to use a `\u003cscript\u003e` tag, you can require MiniSearch\n[from a CDN](https://www.jsdelivr.com/package/npm/minisearch):\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/minisearch@7.1.2/dist/umd/index.min.js\"\u003e\u003c/script\u003e\n```\n\nIn this case, `MiniSearch` will appear as a global variable in your project.\n\nFinally, if you want to manually build the library, clone the repository and run\n`yarn build` (or `yarn build-minified` for a minified version + source maps).\nThe compiled source will be created in the `dist` folder (UMD, ES6 and ES2015\nmodule versions are provided).\n\n\n## Usage\n\n### Basic usage\n\n```javascript\n// A collection of documents for our examples\nconst documents = [\n  {\n    id: 1,\n    title: 'Moby Dick',\n    text: 'Call me Ishmael. Some years ago...',\n    category: 'fiction'\n  },\n  {\n    id: 2,\n    title: 'Zen and the Art of Motorcycle Maintenance',\n    text: 'I can see by my watch...',\n    category: 'fiction'\n  },\n  {\n    id: 3,\n    title: 'Neuromancer',\n    text: 'The sky above the port was...',\n    category: 'fiction'\n  },\n  {\n    id: 4,\n    title: 'Zen and the Art of Archery',\n    text: 'At first sight it must seem...',\n    category: 'non-fiction'\n  },\n  // ...and more\n]\n\nlet miniSearch = new MiniSearch({\n  fields: ['title', 'text'], // fields to index for full-text search\n  storeFields: ['title', 'category'] // fields to return with search results\n})\n\n// Index all documents\nminiSearch.addAll(documents)\n\n// Search with default options\nlet results = miniSearch.search('zen art motorcycle')\n// =\u003e [\n//   { id: 2, title: 'Zen and the Art of Motorcycle Maintenance', category: 'fiction', score: 2.77258, match: { ... } },\n//   { id: 4, title: 'Zen and the Art of Archery', category: 'non-fiction', score: 1.38629, match: { ... } }\n// ]\n```\n\n### Search options\n\n`MiniSearch` supports several options for more advanced search behavior:\n\n```javascript\n// Search only specific fields\nminiSearch.search('zen', { fields: ['title'] })\n\n// Boost some fields (here \"title\")\nminiSearch.search('zen', { boost: { title: 2 } })\n\n// Prefix search (so that 'moto' will match 'motorcycle')\nminiSearch.search('moto', { prefix: true })\n\n// Search within a specific category\nminiSearch.search('zen', {\n  filter: (result) =\u003e result.category === 'fiction'\n})\n\n// Fuzzy search, in this example, with a max edit distance of 0.2 * term length,\n// rounded to nearest integer. The mispelled 'ismael' will match 'ishmael'.\nminiSearch.search('ismael', { fuzzy: 0.2 })\n\n// You can set the default search options upon initialization\nminiSearch = new MiniSearch({\n  fields: ['title', 'text'],\n  searchOptions: {\n    boost: { title: 2 },\n    fuzzy: 0.2\n  }\n})\nminiSearch.addAll(documents)\n\n// It will now by default perform fuzzy search and boost \"title\":\nminiSearch.search('zen and motorcycles')\n```\n\n### Auto suggestions\n\n`MiniSearch` can suggest search queries given an incomplete query:\n\n```javascript\nminiSearch.autoSuggest('zen ar')\n// =\u003e [ { suggestion: 'zen archery art', terms: [ 'zen', 'archery', 'art' ], score: 1.73332 },\n//      { suggestion: 'zen art', terms: [ 'zen', 'art' ], score: 1.21313 } ]\n```\n\nThe `autoSuggest` method takes the same options as the `search` method, so you\ncan get suggestions for misspelled words using fuzzy search:\n\n```javascript\nminiSearch.autoSuggest('neromancer', { fuzzy: 0.2 })\n// =\u003e [ { suggestion: 'neuromancer', terms: [ 'neuromancer' ], score: 1.03998 } ]\n```\n\nSuggestions are ranked by the relevance of the documents that would be returned\nby that search.\n\nSometimes, you might need to filter auto suggestions to, say, only a specific\ncategory. You can do so by providing a `filter` option:\n\n```javascript\nminiSearch.autoSuggest('zen ar', {\n  filter: (result) =\u003e result.category === 'fiction'\n})\n// =\u003e [ { suggestion: 'zen art', terms: [ 'zen', 'art' ], score: 1.21313 } ]\n```\n\n### Field extraction\n\nBy default, documents are assumed to be plain key-value objects with field names\nas keys and field values as simple values. In order to support custom field\nextraction logic (for example for nested fields, or non-string field values that\nneed processing before tokenization), a custom field extractor function can be\npassed as the `extractField` option:\n\n```javascript\n// Assuming that our documents look like:\nconst documents = [\n  { id: 1, title: 'Moby Dick', author: { name: 'Herman Melville' }, pubDate: new Date(1851, 9, 18) },\n  { id: 2, title: 'Zen and the Art of Motorcycle Maintenance', author: { name: 'Robert Pirsig' }, pubDate: new Date(1974, 3, 1) },\n  { id: 3, title: 'Neuromancer', author: { name: 'William Gibson' }, pubDate: new Date(1984, 6, 1) },\n  { id: 4, title: 'Zen in the Art of Archery', author: { name: 'Eugen Herrigel' }, pubDate: new Date(1948, 0, 1) },\n  // ...and more\n]\n\n// We can support nested fields (author.name) and date fields (pubDate) with a\n// custom `extractField` function:\n\nlet miniSearch = new MiniSearch({\n  fields: ['title', 'author.name', 'pubYear'],\n  extractField: (document, fieldName) =\u003e {\n    // If field name is 'pubYear', extract just the year from 'pubDate'\n    if (fieldName === 'pubYear') {\n      const pubDate = document['pubDate']\n      return pubDate \u0026\u0026 pubDate.getFullYear().toString()\n    }\n\n    // Access nested fields\n    return fieldName.split('.').reduce((doc, key) =\u003e doc \u0026\u0026 doc[key], document)\n  }\n})\n```\n\nThe default field extractor can be obtained by calling\n`MiniSearch.getDefault('extractField')`.\n\n### Tokenization\n\nBy default, documents are tokenized by splitting on Unicode space or punctuation\ncharacters. The tokenization logic can be easily changed by passing a custom\ntokenizer function as the `tokenize` option:\n\n```javascript\n// Tokenize splitting by hyphen\nlet miniSearch = new MiniSearch({\n  fields: ['title', 'text'],\n  tokenize: (string, _fieldName) =\u003e string.split('-')\n})\n```\n\nUpon search, the same tokenization is used by default, but it is possible to\npass a `tokenize` search option in case a different search-time tokenization is\nnecessary:\n\n```javascript\n// Tokenize splitting by hyphen\nlet miniSearch = new MiniSearch({\n  fields: ['title', 'text'],\n  tokenize: (string) =\u003e string.split('-'), // indexing tokenizer\n  searchOptions: {\n    tokenize: (string) =\u003e string.split(/[\\s-]+/) // search query tokenizer\n  }\n})\n```\n\nThe default tokenizer can be obtained by calling\n`MiniSearch.getDefault('tokenize')`.\n\n### Term processing\n\nTerms are downcased by default. No stemming is performed, and no stop-word list\nis applied. To customize how the terms are processed upon indexing, for example\nto normalize them, filter them, or to apply stemming, the `processTerm` option\ncan be used. The `processTerm` function should return the processed term as a\nstring, or a falsy value if the term should be discarded:\n\n```javascript\nlet stopWords = new Set(['and', 'or', 'to', 'in', 'a', 'the', /* ...and more */ ])\n\n// Perform custom term processing (here discarding stop words and downcasing)\nlet miniSearch = new MiniSearch({\n  fields: ['title', 'text'],\n  processTerm: (term, _fieldName) =\u003e\n    stopWords.has(term) ? null : term.toLowerCase()\n})\n```\n\nBy default, the same processing is applied to search queries. In order to apply\na different processing to search queries, supply a `processTerm` search option:\n\n```javascript\nlet miniSearch = new MiniSearch({\n  fields: ['title', 'text'],\n  processTerm: (term) =\u003e\n    stopWords.has(term) ? null : term.toLowerCase(), // index term processing\n  searchOptions: {\n    processTerm: (term) =\u003e term.toLowerCase() // search query processing\n  }\n})\n```\n\nThe default term processor can be obtained by calling\n`MiniSearch.getDefault('processTerm')`.\n\n### API Documentation\n\nRefer to the [API\ndocumentation](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html)\nfor details about configuration options and methods.\n\n\n## Browser and Node compatibility\n\n`MiniSearch` supports all browsers and NodeJS versions implementing the ES9\n(ES2018) JavaScript standard. That includes all modern browsers and NodeJS\nversions.\n\nES6 (ES2015) compatibility can be achieved by transpiling the tokenizer RegExp\nto expand Unicode character class escapes, for example with\nhttps://babeljs.io/docs/babel-plugin-transform-unicode-sets-regex.\n\n## Contributing\n\nContributions to `MiniSearch` are welcome. Please read the [contributions\nguidelines](https://github.com/lucaong/minisearch/blob/master/CONTRIBUTING.md).\nReading the [design\ndocument](https://github.com/lucaong/minisearch/blob/master/DESIGN_DOCUMENT.md) is\nalso useful to understand the project goals and the technical implementation.\n","funding_links":[],"categories":["In Memory","TypeScript","JavaScript","Memory","search-engine","Packages","Utilities","Search"],"sub_categories":["React Components","Surveys"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucaong%2Fminisearch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucaong%2Fminisearch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucaong%2Fminisearch/lists"}