{"id":13577820,"url":"https://github.com/typesense/typesense-instantsearch-adapter","last_synced_at":"2025-05-14T14:10:24.777Z","repository":{"id":37692199,"uuid":"240819531","full_name":"typesense/typesense-instantsearch-adapter","owner":"typesense","description":"A JS adapter library to build rich search interfaces with Typesense and InstantSearch.js","archived":false,"fork":false,"pushed_at":"2025-04-02T21:12:06.000Z","size":6229,"stargazers_count":448,"open_issues_count":56,"forks_count":65,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-13T06:15:51.285Z","etag":null,"topics":["algolia","algolia-instantsearch","angular","angular-instantsearch","instantsearch","instantsearch-js","react","react-instantsearch","search","search-interface","search-ui","typesense","typesense-instantsearch-adapter","vue","vue-instantsearch"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/typesense.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2020-02-16T02:30:54.000Z","updated_at":"2025-04-12T10:55:29.000Z","dependencies_parsed_at":"2022-07-08T00:10:33.797Z","dependency_job_id":"d9989125-a716-43c1-a28d-f0a56d2e8485","html_url":"https://github.com/typesense/typesense-instantsearch-adapter","commit_stats":{"total_commits":337,"total_committers":13,"mean_commits":"25.923076923076923","dds":"0.11869436201780414","last_synced_commit":"04d584ce69526a744dc6beb8615ad66ed9d936bd"},"previous_names":[],"tags_count":117,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typesense%2Ftypesense-instantsearch-adapter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typesense%2Ftypesense-instantsearch-adapter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typesense%2Ftypesense-instantsearch-adapter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typesense%2Ftypesense-instantsearch-adapter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/typesense","download_url":"https://codeload.github.com/typesense/typesense-instantsearch-adapter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254160558,"owners_count":22024571,"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":["algolia","algolia-instantsearch","angular","angular-instantsearch","instantsearch","instantsearch-js","react","react-instantsearch","search","search-interface","search-ui","typesense","typesense-instantsearch-adapter","vue","vue-instantsearch"],"created_at":"2024-08-01T15:01:24.611Z","updated_at":"2025-05-14T14:10:19.770Z","avatar_url":"https://github.com/typesense.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Typesense Instantsearch Adapter\n\nAn adapter to use the awesome [Instantsearch.js](https://github.com/algolia/instantsearch.js) library with a [Typesense](https://typesense.org) Search Server, to build rich search interfaces.\n\n[![NPM version][npm-image]][npm-url]\n![downloads](https://img.shields.io/npm/dt/typesense-instantsearch-adapter?label=downloads)\n\nHere is an example of UI you can build with this adapater: [songs-search.typesense.org](https://songs-search.typesense.org)\n\n**Note:** If your search interface is built on a custom autocomplete component, or is based on [@algolia/autocomplete-js](https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/), then you don't need this adapter to use it with Typesense, as [typesense-js](https://github.com/typesense/typesense-js) library already supports client-side fetching data from any async data sources. Read more [here](https://github.com/typesense/typesense-instantsearch-adapter/issues/88#issuecomment-1021597634).\n\n## Quick Links\n\n- [Background](#background)\n- [Quick Start](#quick-start)\n  - [Starter App](#starter-app)\n- [Installation](#installation)\n- [Usage](#usage)\n  - [With instantsearch.js](#with-instantsearchjs)\n  - [With react-instantsearch](#with-react-instantsearch) (also works with React Native)\n  - [With vue-instantsearch](#with-vue-instantsearch)\n  - [With angular-instantsearch](#with-angular-instantsearch)\n- [Widget Specific Instructions](#widget-specific-instructions)\n- [Caching](#caching)\n- [Compatibility](#compatibility)\n- [Development](#development)\n- [Help](#help)\n\n## Background\n\nThe good folks over at Algolia have built and open-sourced [Instantsearch.js](https://github.com/algolia/instantsearch.js) which is a collection of out-of-the-box components that you can use to build interactive search experiences swiftly.\n\nWith the adapter in this repository, you'll be able to use [Instantsearch](https://github.com/algolia/instantsearch.js) (and its [React](https://github.com/algolia/react-instantsearch), [Vue](https://github.com/algolia/vue-instantsearch) and [Angular](https://github.com/algolia/angular-instantsearch) cousins) with data indexed in a Typesense search server.\n\nIf you haven't used Instantsearch before, we recommend going through their Getting Started guide [here](https://www.algolia.com/doc/guides/building-search-ui/getting-started/js/#build-a-simple-ui).\nOnce you go through the guide, follow the instructions below to plug the Typesense adapter into Instantsearch.\n\n## Quick Start\n\nHere's a guide on building a quick search interface with Typesense and InstantSearch.js: [https://typesense.org/docs/0.20.0/guide/search-ui-components.html](https://typesense.org/docs/0.20.0/guide/search-ui-components.html)\n\n### Starter App\n\nHere's a demo starter app that shows you how to use the adapter: [https://github.com/typesense/typesense-instantsearch-demo](https://github.com/typesense/typesense-instantsearch-demo)\n\n## Installation\n\n```shell\n$ npm install --save typesense-instantsearch-adapter @babel/runtime\n```\n\nor\n\n```shell\n$ yarn add typesense-instantsearch-adapter @babel/runtime\n```\n\nor, you can also directly include the adapter via a script tag in your HTML:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/typesense-instantsearch-adapter@2/dist/typesense-instantsearch-adapter.min.js\"\u003e\u003c/script\u003e\n\n\u003c!-- You might want to pin the version of the adapter used if you don't want to always receive the latest minor version --\u003e\n```\n\nSince this is an adapter, it **will not install** the Instantsearch library automatically for you. You need to install one of the following in your application directly:\n\n- [instantsearch.js](https://github.com/algolia/instantsearch.js)\n- [react-instantsearch](https://github.com/algolia/react-instantsearch)\n- [vue-instantsearch](https://github.com/algolia/vue-instantsearch)\n- [angular-instantsearch](https://github.com/algolia/angular-instantsearch)\n\nYou'll find information on how to get started with each of the above libraries in their respective repos.\n\nWe'd also recommend checking out [create-instantsearch-app](https://github.com/algolia/create-instantsearch-app) to create your Search UI from a starter template.\n\n## Usage\n\n### With [instantsearch.js](https://github.com/algolia/instantsearch.js)\n\n```javascript\nimport instantsearch from \"instantsearch.js\";\nimport { searchBox, hits } from \"instantsearch.js/es/widgets\";\nimport TypesenseInstantSearchAdapter from \"typesense-instantsearch-adapter\";\n\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"abcd\", // Be sure to use an API key that only allows search operations\n    nodes: [\n      {\n        host: \"localhost\",\n        path: \"\", // Optional. Example: If you have your typesense mounted in localhost:8108/typesense, path should be equal to '/typesense'\n        port: \"8108\",\n        protocol: \"http\",\n      },\n    ],\n    cacheSearchResultsForSeconds: 2 * 60, // Cache search results from server. Defaults to 2 minutes. Set to 0 to disable caching.\n  },\n  // The following parameters are directly passed to Typesense's search API endpoint.\n  //  So you can pass any parameters supported by the search endpoint below.\n  //  query_by is required.\n  additionalSearchParameters: {\n    query_by: \"name,description,categories\",\n  },\n});\nconst searchClient = typesenseInstantsearchAdapter.searchClient;\n\nconst search = instantsearch({\n  searchClient,\n  indexName: \"products\",\n});\nsearch.addWidgets([\n  searchBox({\n    container: \"#searchbox\",\n  }),\n  hits({\n    container: \"#hits\",\n    templates: {\n      item: `\n        \u003cdiv class=\"hit-name\"\u003e\n          {{#helpers.highlight}}{ \"attribute\": \"name\" }{{/helpers.highlight}}\n        \u003c/div\u003e\n      `,\n    },\n  }),\n]);\n\nsearch.start();\n```\n\nYou can add any of the Instantsearch widgets [here](https://www.algolia.com/doc/guides/building-search-ui/widgets/showcase/js/) that are [supported](#widget-compatibility) by the adapter.\n\nYou'll also find a working example in [test/support/testground](test/support/testground). To run it, run `npm run testground` from the project root folder.\n\n### With [react-instantsearch](https://github.com/algolia/react-instantsearch)\n\n```jsx harmony\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { SearchBox } from \"react-instantsearch-dom\";\nimport TypesenseInstantSearchAdapter from \"typesense-instantsearch-adapter\";\n\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"abcd\", // Be sure to use an API key that only allows search operations\n    nodes: [\n      {\n        host: \"localhost\",\n        port: \"8108\",\n        path: \"\", // Optional. Example: If you have your typesense mounted in localhost:8108/typesense, path should be equal to '/typesense'\n        protocol: \"http\",\n      },\n    ],\n    cacheSearchResultsForSeconds: 2 * 60, // Cache search results from server. Defaults to 2 minutes. Set to 0 to disable caching.\n  },\n  // The following parameters are directly passed to Typesense's search API endpoint.\n  //  So you can pass any parameters supported by the search endpoint below.\n  //  query_by is required.\n  additionalSearchParameters: {\n    query_by: \"name,description,categories\",\n  },\n});\nconst searchClient = typesenseInstantsearchAdapter.searchClient;\n\nconst App = () =\u003e (\n  \u003cInstantSearch indexName=\"products\" searchClient={searchClient}\u003e\n    \u003cSearchBox /\u003e\n    \u003cHits /\u003e\n  \u003c/InstantSearch\u003e\n);\n```\n\nYou can then add any of the Instantsearch-React widgets [here](https://www.algolia.com/doc/guides/building-search-ui/widgets/showcase/react/) that are [supported](#widget-compatibility) by the adapter.\n\nThe instructions above also apply to React Native.\n\n### With [vue-instantsearch](https://github.com/algolia/vue-instantsearch)\n\nApp.vue:\n\n```vue\n\u003ctemplate\u003e\n  \u003cais-instant-search :search-client=\"searchClient\" index-name=\"products\"\u003e\n    \u003cais-search-box /\u003e\n    \u003cais-hits\u003e\n      \u003cdiv slot=\"item\" slot-scope=\"{ item }\"\u003e\n        \u003ch2\u003e{{ item.name }}\u003c/h2\u003e\n      \u003c/div\u003e\n    \u003c/ais-hits\u003e\n  \u003c/ais-instant-search\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport TypesenseInstantSearchAdapter from \"typesense-instantsearch-adapter\";\n\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"abcd\", // Be sure to use an API key that only allows search operations\n    nodes: [\n      {\n        host: \"localhost\",\n        path: \"\", // Optional. Example: If you have your typesense mounted in localhost:8108/typesense, path should be equal to '/typesense'\n        port: \"8108\",\n        protocol: \"http\",\n      },\n    ],\n    cacheSearchResultsForSeconds: 2 * 60, // Cache search results from server. Defaults to 2 minutes. Set to 0 to disable caching.\n  },\n  // The following parameters are directly passed to Typesense's search API endpoint.\n  //  So you can pass any parameters supported by the search endpoint below.\n  //  query_by is required.\n  additionalSearchParameters: {\n    query_by: \"name,description,categories\",\n  },\n});\nconst searchClient = typesenseInstantsearchAdapter.searchClient;\n\nexport default {\n  data() {\n    return {\n      searchClient,\n    };\n  },\n};\n\u003c/script\u003e\n```\n\nYou can then add any of the Instantsearch widgets [here](https://www.algolia.com/doc/guides/building-search-ui/widgets/showcase/vue/) that are [supported](#widget-compatibility) by the adapter.\n\n### With [angular-instantsearch](https://github.com/algolia/angular-instantsearch)\n\n```javascript\n// app.component.ts\nimport { Component } from \"@angular/core\";\nimport TypesenseInstantSearchAdapter from \"typesense-instantsearch-adapter\";\n\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"abcd\", // Be sure to use an API key that only allows search operations\n    nodes: [\n      {\n        host: \"localhost\",\n        path: \"\", // Optional. Example: If you have your typesense mounted in localhost:8108/typesense, path should be equal to '/typesense'\n        port: \"8108\",\n        protocol: \"http\",\n      },\n    ],\n    cacheSearchResultsForSeconds: 2 * 60, // Cache search results from server. Defaults to 2 minutes. Set to 0 to disable caching.\n  },\n  // The following parameters are directly passed to Typesense's search API endpoint.\n  //  So you can pass any parameters supported by the search endpoint below.\n  //  query_by is required.\n  additionalSearchParameters: {\n    query_by: \"name,description,categories\",\n  },\n});\nconst searchClient = typesenseInstantsearchAdapter.searchClient;\n\n@Component({\n  selector: \"app-root\",\n  templateUrl: \"./app.component.html\",\n  styleUrls: [\"./app.component.css\"],\n})\nexport class AppComponent {\n  config = {\n    indexName: \"products\",\n    searchClient,\n  };\n}\n```\n\nYou can then add any of the Instantsearch widgets [here](https://www.algolia.com/doc/guides/building-search-ui/widgets/showcase/angular/) that are [supported](#widget-compatibility) by the adapter.\n\n## Widget Specific Instructions\n\n### `hierarchicalMenu`\n\nFor this widget, you want to create independent fields in the collection's schema with this specific naming convention:\n\n- `field.lvl0`\n- `field.lvl1`\n- `field.lvl2`\n\nfor a nested hierarchy of `field.lvl0 \u003e field.lvl1 \u003e field.lvl2`\n\nEach of these fields can also hold an array of values. This is useful for handling multiple hierarchies.\n\n### `sortBy`\n\nWhen instantiating this widget, you want to set the value of the index name to this particular format:\n\n```javascript\nsearch.addWidgets([\n  sortBy({\n    container: \"#sort-by\",\n    items: [\n      { label: \"Default\", value: \"products\" },\n      { label: \"Price (asc)\", value: \"products/sort/price:asc\" },\n      { label: \"Price (desc)\", value: \"products/sort/price:desc\" },\n    ],\n  }),\n]);\n```\n\nThe generalized pattern for the value attribute is: `\u003cindex_name\u003e[/sort/\u003csort_by\u003e]`. The adapter will use the value in `\u003csort_by\u003e` as the value for the `sort_by` search parameter.\n\n### `configure`\n\nIf you need to specify a `filter_by` search parameter for Typesense, you want to use the `configure` InstantSearch widget, along with `facetFilters`, `numericFilters` or `filters`.\n\nThe format for `facetFilters` and `numericFilters` is the same as Algolia's as described [here](https://www.algolia.com/doc/api-reference/api-parameters/facetFilters/).\nBut `filters` needs to be in Typesense's `filter_by` format as described in this table [here](https://typesense.org/docs/latest/api/documents.html#query-parameters).\n\nSetting `filter_by` inside the `additionalQueryParameters` config only works when the widgets are loaded initially, because InstantSearch internally overrides the `filter_by` field subsequently.\nRead more [here](https://github.com/typesense/typesense-instantsearch-adapter/issues/17#issuecomment-746912375).\n\n### `index`\n\nFor Federated / Multi-Index Search, you'd need to use the `index` widget. To then be able to specify different search parameters for each index/collection, you can specify them using the `collectionSpecificSearchParameters` configuration:\n\n```js\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"abcd\", // Be sure to use an API key that only allows search operations\n    nodes: [{ host: \"localhost\", path: \"/\", port: \"8108\", protocol: \"http\" }],\n  },\n  // Search parameters that are common to all collections/indices go here:\n  additionalSearchParameters: {\n    numTypos: 3,\n  },\n  // Search parameters that need to be *overridden* on a per-collection-basis go here:\n  collectionSpecificSearchParameters: {\n    products: {\n      query_by: \"name,description,categories\",\n    },\n    brands: {\n      query_by: \"name\",\n    },\n  },\n});\nconst searchClient = typesenseInstantsearchAdapter.searchClient;\n```\n\nEssentially, any parameters set in `collectionSpecificSearchParameters` will be merged with the values in `additionalSearchParameters` when querying Typesense, effectively overriding values in `additionalSearchParameters` on a per-collection-basis.\n\n### `geoSearch`\n\nAlgolia uses `_geoloc` by default for the name of the field that stores the lat long values for a record.\nIn Typesense, you can name the geo location field anything. If you use a name other than `_geoloc`, you need to specify it when initializing the adapter like below, so InstantSearch can access it:\n\n```js\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"xyz\",\n    nodes: [\n      {\n        host: \"localhost\",\n        port: \"8108\",\n        path: \"/\",\n        protocol: \"http\",\n      },\n    ],\n  },\n  geoLocationField: \"lat_lng_field\", // \u003c\u003c======\n  additionalSearchParameters,\n});\n```\n\n### `dynamicWidgets`\n\n\u003e Available as of Typesense Server `v0.25.0.rc12`\n\nThis [`dynamicWidgets`](https://www.algolia.com/doc/api-reference/widgets/dynamic-facets/js/) widget works out of the box with no additional changes,\nbut if you want to control the order in which these facets are displayed in the UI\nInstantsearch expects a parameter called [`renderingContent`](https://www.algolia.com/doc/api-reference/api-parameters/renderingContent/) to be set.\n\n```js\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"xyz\",\n    nodes: [\n      {\n        host: \"localhost\",\n        port: \"8108\",\n        path: \"/\",\n        protocol: \"http\",\n      },\n    ],\n  },\n  renderingContent: {\n    // \u003c\u003c===== Add this, only if you want to control the order of the widgets displayed by dynamicWidgets\n    facetOrdering: {\n      facets: {\n        order: [\"size\", \"brand\"], // \u003c\u003c===== Change this as needed\n      },\n    },\n  },\n  additionalSearchParameters,\n});\n```\n\nRead more about all available options for `renderingContent` in [Algolia's documentation here](https://www.algolia.com/doc/api-reference/api-parameters/renderingContent/?client=javascript#examples).\n\n### Special characters in field names / values\n\n\u003e Available as of typesense-instantsearch-adapter `2.7.0-2`\n\n- If any string fields in your documents have a colon `:` in their values (for eg, let's say there's a field called `{ brand: \"a:b\" }`, then you would need to add a parameter like below when instantiating the adapter:\n\n  ```js\n  const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n    server: {\n      apiKey: \"xyz\",\n      nodes: [\n        {\n          host: \"localhost\",\n          port: \"8108\",\n          path: \"/\",\n          protocol: \"http\",\n        },\n      ],\n    },\n    facetableFieldsWithSpecialCharacters: [\"brand\"], // \u003c======= Add string fields that have colons in their values here, to aid in parsing\n    additionalSearchParameters,\n  });\n  ```\n\n- If any numeric field _names_ in your documents have special characters like `\u003e`, `\u003c`, `=` (for eg, let's say there's a field called `{ price\u003ediscount: 3.0 }`) then you would need to add a parameter like below when instantiating the adapter:\n\n  ```js\n  const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n    server: {\n      apiKey: \"xyz\",\n      nodes: [\n        {\n          host: \"localhost\",\n          port: \"8108\",\n          path: \"/\",\n          protocol: \"http\",\n        },\n      ],\n    },\n    facetableFieldsWithSpecialCharacters: [\"price\u003ediscount\"], // // \u003c======= Add numeric fields that have \u003e, \u003c or = in their names, to aid in parsing\n    additionalSearchParameters,\n  });\n  ```\n\n### Setting `facet_by` options\n\n\u003e Available as of typesense-instantsearch-adapter `2.8.0-1` and Typesense Server `v0.26.0.rc25`\n\nThe `facet_by` parameter is managed by InstantSearch internally when you use the various filter widgets.\n\nBut if you need to pass custom options to the `facet_by` parameter (eg: server-side sort options), then you can use the `facetByOptions` parameter as shown below:\n\n```js\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"xyz\",\n    nodes: [\n      {\n        host: \"localhost\",\n        port: \"8108\",\n        path: \"/\",\n        protocol: \"http\",\n      },\n    ],\n  },\n  facetByOptions: {\n    brand: \"(sort_by: _alpha:asc)\",\n    category: \"(sort_by: _alpha:desc)\",\n  }, // \u003c======= Add any facet_by parameter as a key value pair. Don't forget the surrounding parantheses in the value.\n  collectionSpecificFacetByOptions: {\n    collection1: {\n      brand: \"(sort_by: _alpha:desc)\",\n    },\n  }, // \u003c======= Use this parameter if multiple collections share the same field names, and you want to use different options for each field. This will override facetByOptions for that particular collection.\n  additionalSearchParameters,\n});\n```\n\nNote that for sorting in refinementLists, in addition to sorting on the Typesense Server-side, you'd also need to pass the [`sortBy`](https://www.algolia.com/doc/api-reference/widgets/refinement-list/js/#widget-param-sortby) parameter to the refinementList widget to also sort the results appropriately on the client-side.\n\n### Setting `filter_by` options\n\n\u003e Available as of typesense-instantsearch-adapter `2.8.0-5`\n\nThe `filter_by` parameter is managed by InstantSearch internally when you use the various filter widgets.\n\nBy default, the adapter uses exact filtering (`filter_by: field:=value`) when sending the queries to Typesense.\nIf you need to configure the adapter to use `:` (non-exact word-level filtering - `filter_by: field:value`), you want to instantiate the adapter using the `filterByOptions` configuration:\n\n```js\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"xyz\",\n    nodes: [\n      {\n        host: \"localhost\",\n        port: \"8108\",\n        path: \"/\",\n        protocol: \"http\",\n      },\n    ],\n  },\n  filterByOptions: {\n    brand: { exactMatch: false }, // \u003c========== Add this to do non-exact word-level filtering\n    category: { exactMatch: false },\n  },\n  collectionSpecificFilterByOptions: {\n    collection1: {\n      brand: { exactMatch: false },\n    },\n  }, // \u003c======= Use this parameter if multiple collections share the same field names, and you want to use different options for each field. This will override filterByOptions for that particular collection.\n  additionalSearchParameters,\n});\n```\n\n### Disabling overrides for certain sorts\n\n\u003e Available as of typesense-instantsearch-adapter `2.9.0-0`\n\nHere's a way to disable overrides / curation rules, when users select a particular sort order:\n\n```js\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"xyz\",\n    nodes: [\n      {\n        host: \"localhost\",\n        port: \"8108\",\n        path: \"/\",\n        protocol: \"http\",\n      },\n    ],\n  },\n  sortByOptions: {\n    \"field1:desc,field2:desc\": { enable_overrides: false }, // \u003c========== Add this to disable sorting when this particular Typesense `sort_by` string is generated by the sortBy widget\n  },\n  collectionSpecificSortByOptions: {\n    collection2: {\n      \"field1:desc,field2:desc\": { enable_overrides: false },\n    },\n  }, // \u003c======= Use this parameter if multiple collections share the same field names, and you want to use different options for each field. This will override sortByOptions for that particular collection.\n  additionalSearchParameters,\n});\n```\n\nIf you have a sortBy widgets configured with an indexName value of `products/sort/price:asc` for eg, then the key inside `sortByOptions` should be `price:asc`.\n\n### Grouped Hits\n\n\u003e Available as of typesense-instantsearch-adapter `2.7.1-4`\n\nBy default, when `group_by` is used as a search parameters, the adapter flattens the results across all groups into a single list of sequential hits.\n\nIf you'd like to preserve the groups, you want to set `flattenGroupedHits: false` when instantiating the adapter.\n\nThis will place the first hit in a group as the primary hit, and then add all hits in the group inside a `_grouped_hits` key inside each hit.\n\n```js\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"xyz\",\n    nodes: [\n      {\n        host: \"localhost\",\n        port: \"8108\",\n        path: \"/\",\n        protocol: \"http\",\n      },\n    ],\n  },\n  flattenGroupedHits: false, // \u003c=======\n  additionalSearchParameters,\n});\n```\n\n### Vector Search\n\n\u003e Available as of typesense-instantsearch-adapter `2.7.0-3`\n\nThe general idea is to first hook into the query life-cycle of Instantsearch, intercept the typed query and send it to an embedding API, fetch the embeddings and then send the vectors to Typesense to do a nearest neighbor vector search.\n\nHere's a demo that you can run locally to see this in action: [https://github.com/typesense/showcase-hn-comments-semantic-search](https://github.com/typesense/showcase-hn-comments-semantic-search).\n\nHere's how to do this in Instantsearch.js:\n\n```javascript\nconst typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n  server: {\n    apiKey: \"xyz\",\n    nodes: [\n      {\n        host: \"localhost\",\n        port: \"8108\",\n        path: \"/\",\n        protocol: \"http\",\n      },\n    ],\n  },\n  additionalSearchParameters,\n});\n// from https://github.com/typesense/showcase-hn-comments-semantic-search/blob/8a33006cae58b425c53f56a64e1273e808cd9375/src/js/index.js#L101\nconst searchClient = typesenseInstantsearchAdapter.searchClient;\nsearch = instantsearch({\n  searchClient,\n  indexName: INDEX_NAME,\n  routing: true,\n  async searchFunction(helper) {\n    // This fetches 200 (nearest neighbor) results for semantic / hybrid search\n\n    let query = helper.getQuery().query;\n    const page = helper.getPage(); // Retrieve the current page\n\n    if (query !== \"\" \u0026\u0026 [\"semantic\", \"hybrid\"].includes($(\"#search-type-select\").val())) {\n      console.log(helper.getQuery().query);\n      helper\n        .setQueryParameter(\n          \"typesenseVectorQuery\", // \u003c=== Special parameter that only works in typesense-instantsearch-adapter@2.7.0-3 and above\n          `embedding:([], k:200)`,\n        )\n        .setPage(page)\n        .search();\n      console.log(helper.getQuery().query);\n    } else {\n      helper.setQueryParameter(\"typesenseVectorQuery\", null).setPage(page).search();\n    }\n  },\n});\n```\n\n## Caching\n\nThere are two modes of caching:\n\n1. **Server-side caching:**\n\n   To enable server-side caching, add a parameter called `useServerSideSearchCache: true` in the `server` configuration block of the typesense-instantsearch-adapter like this:\n\n   ```javascript\n   const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n     server: {\n       apiKey: \"...\",\n       nearestNode: {...},\n       nodes: [...],\n       useServerSideSearchCache: true // \u003c\u003c\u003c Add this to send use_cache as a query parameter instead of post body parameter\n     },\n     additionalSearchParameters: {...}\n   });\n   ```\n\n   This will cause the adapter to add `?use_cache=true` as a URL query parameter to all search requests initiated by the adapter, which will then cause Typesense Server to enable server-side caching for these requests.\n\n2. **Client-side caching:**\n\n   The adapter also has client-side caching enabled by default, to prevent unnecessary network calls to the server. The TTL for this client-side cache can be configured like this:\n\n   ```javascript\n   const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({\n    server: {\n      apiKey: \"...\",\n      nearestNode: {...},\n      nodes: [...],\n      cacheSearchResultsForSeconds: 2 * 60 // \u003c\u003c\u003c Add this to configure the TTL for client-side cache in the browser\n    },\n    additionalSearchParameters: {...}\n   });\n   ```\n\n## Compatibility\n\n| Typesense Server | typesense-instantsearch-adapter | instantsearch.js | react-instantsearch | vue-instantsearch | angular-instantsearch |\n| ---------------- | ------------------------------- | ---------------- | ------------------- | ----------------- | --------------------- |\n| \\\u003e= v0.25.0      | \\\u003e= v2.7.1                      | \\\u003e= 4.51         | \\\u003e= 6.39            | \\\u003e= 4.8           | \\\u003e= 4.4               |\n| \\\u003e= v0.25.0.rc14 | \\\u003e= v2.7.0-1                    | \\\u003e= 4.51         | \\\u003e= 6.39            | \\\u003e= 4.8           | \\\u003e= 4.4               |\n| \\\u003e= v0.25.0.rc12 | \\\u003e= v2.6.0                      | \\\u003e= 4.51         | \\\u003e= 6.39            | \\\u003e= 4.8           | \\\u003e= 4.4               |\n| \\\u003e= v0.24        | \\\u003e= v2.5.0                      | \\\u003e= 4.2.0        | \\\u003e= 6.0.0           | \\\u003e= 2.2.1         | \\\u003e= 3.0.0             |\n| \\\u003e= v0.21        | \\\u003e= v2.0.0                      | \\\u003e= 4.2.0        | \\\u003e= 6.0.0           | \\\u003e= 2.2.1         | \\\u003e= 3.0.0             |\n| \\\u003e= v0.19        | \\\u003e= v1.0.0                      | \\\u003e= 4.2.0        | \\\u003e= 6.0.0           | \\\u003e= 2.2.1         | \\\u003e= 3.0.0             |\n| \\\u003e= v0.15        | \\\u003e= v0.3.0                      | \\\u003e= 4.2.0        | \\\u003e= 6.0.0           | \\\u003e= 2.2.1         | \\\u003e= 3.0.0             |\n| \\\u003e= v0.14        | \\\u003e= v0.2.0                      | \\\u003e= 4.2.0        | \\\u003e= 6.0.0           | \\\u003e= 2.2.1         | \\\u003e= 3.0.0             |\n| \\\u003e= v0.13        | \\\u003e= v0.1.0                      | \\\u003e= 4.2.0        | \\\u003e= 6.0.0           | \\\u003e= 2.2.1         | \\\u003e= 3.0.0             |\n| \\\u003e= v0.12        | \\\u003e= v0.0.4                      | \\\u003e= 4.2.0        | \\\u003e= 6.0.0           | \\\u003e= 2.2.1         | \\\u003e= 3.0.0             |\n\nIf a particular version of the above libraries don't work with the adapter, please open a Github issue with details.\n\n### Widget Compatibility\n\nThis adapter works with all widgets in [this list](https://www.algolia.com/doc/api-reference/widgets/js/)\n\n## Development\n\n```shell\n$ npm install\n$ npm run typesenseServer\n$ FORCE_REINDEX=true npm run indexTestData\n\n$ npm link typesense-instantsearch-adapter\n$ npm run testground\n\n$ npm test\n```\n\nTo release a new version, we use the [np](https://github.com/sindresorhus/np) package:\n\n```shell\n$ npm install --global np\n$ np\n\n# Follow instructions that np shows you\n\n```\n\n## Help\n\nIf you have any questions or run into any problems, please create a Github issue and we'll try our best to help.\n\n© 2020-present Typesense, Inc.\n\n[npm-image]: https://badge.fury.io/js/typesense-instantsearch-adapter.svg\n[npm-url]: https://npmjs.org/package/typesense-instantsearch-adapter\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypesense%2Ftypesense-instantsearch-adapter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftypesense%2Ftypesense-instantsearch-adapter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypesense%2Ftypesense-instantsearch-adapter/lists"}