JSPM

@vectorhook/instantsearch

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 54
  • Score
    100M100P100Q12233F
  • License MIT

VectorHook adapter for Algolia InstantSearch

Package Exports

  • @vectorhook/instantsearch

Readme

@vectorhook/instantsearch

npm version License: MIT

An adapter that lets you use Algolia's InstantSearch frontend libraries with VectorHook as the backend search engine.

This adapter translates queries from InstantSearch libraries (vanilla JS, React, Vue, Angular) to VectorHook's search API format, allowing you to leverage InstantSearch's rich UI components while using VectorHook's powerful search capabilities.

Installation

# npm
npm install @vectorhook/instantsearch @vectorhook/client instantsearch.js

# or yarn
yarn add @vectorhook/instantsearch @vectorhook/client instantsearch.js

# For React InstantSearch
npm install react-instantsearch-dom

# For Vue InstantSearch
npm install vue-instantsearch

Quick Start

// Initialize VectorHook client
import VectorHook from '@vectorhook/client';
import VectorHookInstantSearch from '@vectorhook/instantsearch';
import instantsearch from 'instantsearch.js';
import { searchBox, hits } from 'instantsearch.js/es/widgets';

// Initialize VectorHook client
const vectorhookClient = new VectorHook({
  apiKey: 'your_api_key',
  baseUrl: 'https://api.vectorhook.com'
});

// Initialize the InstantSearch adapter
const searchClient = new VectorHookInstantSearch({
  vectorhookClient: vectorhookClient,
  collectionName: 'products',
  mappings: {
    queryBy: 'name,description',
    facetBy: 'categories,brand,in_stock'
  }
});

// Create the InstantSearch instance
const search = instantsearch({
  indexName: 'products',
  searchClient
});

// Add widgets
search.addWidgets([
  searchBox({
    container: '#searchbox',
  }),
  hits({
    container: '#hits',
    templates: {
      item: (hit) => `
        <div>
          <h3>${hit.name}</h3>
          <p>${hit.description}</p>
          <p>$${hit.price}</p>
        </div>
      `
    }
  })
]);

// Start the search
search.start();

Framework Integrations

React InstantSearch

import React from 'react';
import VectorHook from '@vectorhook/client';
import VectorHookInstantSearch from '@vectorhook/instantsearch';
import { InstantSearch, SearchBox, Hits, RefinementList } from 'react-instantsearch-dom';

const vectorhookClient = new VectorHook({
  apiKey: 'your_api_key',
  baseUrl: 'https://api.vectorhook.com'
});

const searchClient = new VectorHookInstantSearch({
  vectorhookClient: vectorhookClient,
  collectionName: 'products',
  mappings: {
    queryBy: 'name,description',
    facetBy: 'categories,brand'
  }
});

function App() {
  return (
    <InstantSearch indexName="products" searchClient={searchClient}>
      <div className="search-panel">
        <div className="search-panel__filters">
          <RefinementList attribute="categories" />
          <RefinementList attribute="brand" />
        </div>
        <div className="search-panel__results">
          <SearchBox />
          <Hits hitComponent={Hit} />
        </div>
      </div>
    </InstantSearch>
  );
}

function Hit({ hit }) {
  return (
    <article>
      <h1>{hit.name}</h1>
      <p>{hit.description}</p>
      <p>${hit.price}</p>
    </article>
  );
}

export default App;

Vue InstantSearch

<template>
  <ais-instant-search
    :search-client="searchClient"
    index-name="products"
  >
    <div class="search-panel">
      <div class="search-panel__filters">
        <ais-refinement-list attribute="categories" />
        <ais-refinement-list attribute="brand" />
      </div>
      <div class="search-panel__results">
        <ais-search-box />
        <ais-hits>
          <template slot="item" slot-scope="{ item }">
            <h1>{{ item.name }}</h1>
            <p>{{ item.description }}</p>
            <p>${{ item.price }}</p>
          </template>
        </ais-hits>
      </div>
    </div>
  </ais-instant-search>
</template>

<script>
import VectorHook from '@vectorhook/client';
import VectorHookInstantSearch from '@vectorhook/instantsearch';

export default {
  data() {
    const vectorhookClient = new VectorHook({
      apiKey: 'your_api_key',
      baseUrl: 'https://api.vectorhook.com'
    });

    const searchClient = new VectorHookInstantSearch({
      vectorhookClient: vectorhookClient,
      collectionName: 'products',
      mappings: {
        queryBy: 'name,description',
        facetBy: 'categories,brand'
      }
    });

    return {
      searchClient
    };
  }
};
</script>

Configuration Options

The VectorHookInstantSearch constructor accepts the following options:

const searchClient = new VectorHookInstantSearch({
  // Required options
  vectorhookClient: vectorhookClient, // Initialized VectorHook client
  collectionName: 'products',         // VectorHook collection to search

  // Field mapping options
  mappings: {
    // Fields to search (comma-separated)
    queryBy: 'name,description',
    
    // Fields for faceting (comma-separated)
    facetBy: 'categories,brand,in_stock',
    
    // Field used for tag filtering
    tagsField: 'tags',
    
    // Field for geo search
    geoField: '_geo',
    
    // Map Algolia field names to VectorHook field names
    facetMap: {
      'category': 'categories',
      'author.name': 'author_name'
    },
    
    // Map index names to sort options
    sortMap: {
      'products_price_asc': 'price:asc',
      'products_price_desc': 'price:desc'
    },
    
    // Default sort when none specified
    defaultSort: 'price:asc'
  },
  
  // Additional query parameters to include in all searches
  additionalQueryParams: {
    group_limit: 3,
    typo_tolerance_enabled: false
  },
  
  // Performance options
  requestTimeout: 5000,  // Timeout in ms
  maxRetries: 2,         // Max retries for failed requests
  
  // Debug mode
  debug: false           // Set to true for verbose logging
});

Features

  • Full Compatibility: Works with all InstantSearch libraries (JS, React, Vue, Angular)
  • Faceting: Supports refinement lists, hierarchical menus, and range sliders
  • Pagination: Works seamlessly with InstantSearch's pagination components
  • Sorting: Supports multiple indices for different sort orders
  • Highlighting: Converts VectorHook highlights to InstantSearch format
  • Error Handling: Built-in retries for failed requests
  • Customization: Extensive mapping options for field names and behaviors

Field Mapping

Default Field Mappings

VectorHook's field names might be different from what InstantSearch expects. The adapter provides mapping options to handle these differences:

const searchClient = new VectorHookInstantSearch({
  // ...other options
  mappings: {
    // Map Algolia field names to VectorHook field names
    facetMap: {
      'category': 'categories',      // InstantSearch uses 'category', VectorHook uses 'categories'
      'author.name': 'author_name'   // Handle nested fields
    }
  }
});

Sort Mapping

For sorting, InstantSearch typically uses different indices with specific names. The adapter maps these index names to VectorHook sort parameters:

const searchClient = new VectorHookInstantSearch({
  // ...other options
  mappings: {
    sortMap: {
      'products_price_asc': 'price:asc',
      'products_price_desc': 'price:desc',
      'products_created_at_desc': 'created_at:desc'
    }
  }
});

Advanced Usage

For multi-index searching (e.g., for sorting):

// instantsearch.js
const search = instantsearch({
  indexName: 'products',
  searchClient
});

// Add a sort-by widget
search.addWidgets([
  sortBy({
    container: '#sort-by',
    items: [
      { label: 'Default', value: 'products' },
      { label: 'Price (asc)', value: 'products_price_asc' },
      { label: 'Price (desc)', value: 'products_price_desc' }
    ]
  })
]);

The adapter will map these index names to VectorHook sort parameters based on your sortMap configuration.

Custom Highlighting

Configure highlighting parameters:

const searchClient = new VectorHookInstantSearch({
  // ...other options
  additionalQueryParams: {
    highlight_fields: 'name,description',
    highlight_start_tag: '<mark>',
    highlight_end_tag: '</mark>'
  }
});

For geo search capabilities:

// React InstantSearch
<InstantSearch indexName="products" searchClient={searchClient}>
  <Configure aroundLatLng="40.7128,-74.0060" aroundRadius="1000" />
  {/* Other widgets */}
</InstantSearch>

The adapter will convert these parameters to VectorHook's geo filter format.

API Reference

VectorHookInstantSearch

Constructor

new VectorHookInstantSearch(options)

Methods

Method Description
search(requests) Main method called by InstantSearch to perform searches
setCollection(collectionName) Change the collection being searched
updateOptions(options) Update adapter options
resetOptions() Reset options to initial values
getState() Get current search state
clearCache() Compatibility method (no-op for VectorHook)

Compatibility Notes

Sorting

VectorHook uses sort_by parameter with format field:direction, while InstantSearch typically uses separate indices.

Faceting

The adapter automatically converts InstantSearch facet filters to VectorHook's filter format.

Highlighting

VectorHook's highlighting format is converted to match what InstantSearch expects.

Migration from Algolia

If you're migrating from Algolia to VectorHook, this adapter makes it easier by allowing you to keep your existing InstantSearch UI code. You only need to:

  1. Replace the Algolia client with the VectorHook client and this adapter
  2. Configure the appropriate field mappings
  3. Ensure your VectorHook schema matches your data structure

Troubleshooting

Common Issues

  • Missing facets: Ensure you've added the facet fields to the facetBy option.
  • Incorrect sorting: Check your sortMap configuration.
  • Search not working: Verify your VectorHook API key and collection name.

Debug Mode

Enable debug mode to see detailed logs:

const searchClient = new VectorHookInstantSearch({
  // ...other options
  debug: true
});

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.