GithubHelp home page GithubHelp logo

typesense / typesense-instantsearch-adapter Goto Github PK

View Code? Open in Web Editor NEW
368.0 11.0 63.0 10.47 MB

A JS adapter library to build rich search interfaces with Typesense and InstantSearch.js

License: MIT License

JavaScript 89.36% HTML 7.22% CSS 1.13% TypeScript 2.29%
search search-interface react vue angular instantsearch search-ui vue-instantsearch react-instantsearch angular-instantsearch

typesense-instantsearch-adapter's Introduction

Typesense Instantsearch Adapter

An adapter to use the awesome Instantsearch.js library with a Typesense Search Server, to build rich search interfaces.

NPM version downloads

Here is an example of UI you can build with this adapater: songs-search.typesense.org

Note: If your search interface is built on a custom autocomplete component, or is based on @algolia/autocomplete-js, then you don't need this adapter to use it with Typesense, as typesense-js library already supports client-side fetching data from any async data sources. Read more here.

Quick Links

Background

The good folks over at Algolia have built and open-sourced Instantsearch.js which is a collection of out-of-the-box components that you can use to build interactive search experiences swiftly.

With the adapter in this repository, you'll be able to use Instantsearch (and its React, Vue and Angular cousins) with data indexed in a Typesense search server.

If you haven't used Instantsearch before, we recommend going through their Getting Started guide here. Once you go through the guide, follow the instructions below to plug the Typesense adapter into Instantsearch.

Quick Start

Here'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

Starter App

Here's a demo starter app that shows you how to use the adapter: https://github.com/typesense/typesense-instantsearch-demo

Installation

$ npm install --save typesense-instantsearch-adapter @babel/runtime

or

$ yarn add typesense-instantsearch-adapter @babel/runtime

or, you can also directly include the adapter via a script tag in your HTML:

<script src="https://cdn.jsdelivr.net/npm/typesense-instantsearch-adapter@2/dist/typesense-instantsearch-adapter.min.js"></script>

<!-- You might want to pin the version of the adapter used if you don't want to always receive the latest minor version -->

Since 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:

You'll find information on how to get started with each of the above libraries in their respective repos.

We'd also recommend checking out create-instantsearch-app to create your Search UI from a starter template.

Usage

import instantsearch from "instantsearch.js";
import { searchBox, hits } from "instantsearch.js/es/widgets";
import TypesenseInstantSearchAdapter from "typesense-instantsearch-adapter";

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "abcd", // Be sure to use an API key that only allows search operations
    nodes: [
      {
        host: "localhost",
        path: "", // Optional. Example: If you have your typesense mounted in localhost:8108/typesense, path should be equal to '/typesense'
        port: "8108",
        protocol: "http",
      },
    ],
    cacheSearchResultsForSeconds: 2 * 60, // Cache search results from server. Defaults to 2 minutes. Set to 0 to disable caching.
  },
  // The following parameters are directly passed to Typesense's search API endpoint.
  //  So you can pass any parameters supported by the search endpoint below.
  //  query_by is required.
  additionalSearchParameters: {
    query_by: "name,description,categories",
  },
});
const searchClient = typesenseInstantsearchAdapter.searchClient;

const search = instantsearch({
  searchClient,
  indexName: "products",
});
search.addWidgets([
  searchBox({
    container: "#searchbox",
  }),
  hits({
    container: "#hits",
    templates: {
      item: `
        <div class="hit-name">
          {{#helpers.highlight}}{ "attribute": "name" }{{/helpers.highlight}}
        </div>
      `,
    },
  }),
]);

search.start();

You can add any of the Instantsearch widgets here that are supported by the adapter.

You'll also find a working example in test/support/testground. To run it, run npm run testground from the project root folder.

import React from "react";
import ReactDOM from "react-dom";
import { SearchBox } from "react-instantsearch-dom";
import TypesenseInstantSearchAdapter from "typesense-instantsearch-adapter";

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "abcd", // Be sure to use an API key that only allows search operations
    nodes: [
      {
        host: "localhost",
        port: "8108",
        path: "", // Optional. Example: If you have your typesense mounted in localhost:8108/typesense, path should be equal to '/typesense'
        protocol: "http",
      },
    ],
    cacheSearchResultsForSeconds: 2 * 60, // Cache search results from server. Defaults to 2 minutes. Set to 0 to disable caching.
  },
  // The following parameters are directly passed to Typesense's search API endpoint.
  //  So you can pass any parameters supported by the search endpoint below.
  //  query_by is required.
  additionalSearchParameters: {
    query_by: "name,description,categories",
  },
});
const searchClient = typesenseInstantsearchAdapter.searchClient;

const App = () => (
  <InstantSearch indexName="products" searchClient={searchClient}>
    <SearchBox />
    <Hits />
  </InstantSearch>
);

You can then add any of the Instantsearch-React widgets here that are supported by the adapter.

The instructions above also apply to React Native.

App.vue:

<template>
  <ais-instant-search :search-client="searchClient" index-name="products">
    <ais-search-box />
    <ais-hits>
      <div slot="item" slot-scope="{ item }">
        <h2>{{ item.name }}</h2>
      </div>
    </ais-hits>
  </ais-instant-search>
</template>

<script>
import TypesenseInstantSearchAdapter from "typesense-instantsearch-adapter";

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "abcd", // Be sure to use an API key that only allows search operations
    nodes: [
      {
        host: "localhost",
        path: "", // Optional. Example: If you have your typesense mounted in localhost:8108/typesense, path should be equal to '/typesense'
        port: "8108",
        protocol: "http",
      },
    ],
    cacheSearchResultsForSeconds: 2 * 60, // Cache search results from server. Defaults to 2 minutes. Set to 0 to disable caching.
  },
  // The following parameters are directly passed to Typesense's search API endpoint.
  //  So you can pass any parameters supported by the search endpoint below.
  //  query_by is required.
  additionalSearchParameters: {
    query_by: "name,description,categories",
  },
});
const searchClient = typesenseInstantsearchAdapter.searchClient;

export default {
  data() {
    return {
      searchClient,
    };
  },
};
</script>

You can then add any of the Instantsearch widgets here that are supported by the adapter.

// app.component.ts
import { Component } from "@angular/core";
import TypesenseInstantSearchAdapter from "typesense-instantsearch-adapter";

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "abcd", // Be sure to use an API key that only allows search operations
    nodes: [
      {
        host: "localhost",
        path: "", // Optional. Example: If you have your typesense mounted in localhost:8108/typesense, path should be equal to '/typesense'
        port: "8108",
        protocol: "http",
      },
    ],
    cacheSearchResultsForSeconds: 2 * 60, // Cache search results from server. Defaults to 2 minutes. Set to 0 to disable caching.
  },
  // The following parameters are directly passed to Typesense's search API endpoint.
  //  So you can pass any parameters supported by the search endpoint below.
  //  query_by is required.
  additionalSearchParameters: {
    query_by: "name,description,categories",
  },
});
const searchClient = typesenseInstantsearchAdapter.searchClient;

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class AppComponent {
  config = {
    indexName: "products",
    searchClient,
  };
}

You can then add any of the Instantsearch widgets here that are supported by the adapter.

Widget Specific Instructions

hierarchicalMenu

For this widget, you want to create independent fields in the collection's schema with this specific naming convention:

  • field.lvl0
  • field.lvl1
  • field.lvl2

for a nested hierarchy of field.lvl0 > field.lvl1 > field.lvl2

Each of these fields can also hold an array of values. This is useful for handling multiple hierarchies.

sortBy

When instantiating this widget, you want to set the value of the index name to this particular format:

search.addWidgets([
  sortBy({
    container: "#sort-by",
    items: [
      { label: "Default", value: "products" },
      { label: "Price (asc)", value: "products/sort/price:asc" },
      { label: "Price (desc)", value: "products/sort/price:desc" },
    ],
  }),
]);

The generalized pattern for the value attribute is: <index_name>[/sort/<sort_by>]. The adapter will use the value in <sort_by> as the value for the sort_by search parameter.

configure

If 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.

The format for facetFilters and numericFilters is the same as Algolia's as described here. But filters needs to be in Typesense's filter_by format as described in this table here.

Setting filter_by inside the additionalQueryParameters config only works when the widgets are loaded initially, because InstantSearch internally overrides the filter_by field subsequently. Read more here.

index

For 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:

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "abcd", // Be sure to use an API key that only allows search operations
    nodes: [{ host: "localhost", path: "/", port: "8108", protocol: "http" }],
  },
  // Search parameters that are common to all collections/indices go here:
  additionalSearchParameters: {
    numTypos: 3,
  },
  // Search parameters that need to be *overridden* on a per-collection-basis go here:
  collectionSpecificSearchParameters: {
    products: {
      query_by: "name,description,categories",
    },
    brands: {
      query_by: "name",
    },
  },
});
const searchClient = typesenseInstantsearchAdapter.searchClient;

Essentially, 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.

geoSearch

Algolia uses _geoloc by default for the name of the field that stores the lat long values for a record. In 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:

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "xyz",
    nodes: [
      {
        host: "localhost",
        port: "8108",
        path: "/",
        protocol: "http",
      },
    ],
  },
  geoLocationField: "lat_lng_field", // <<======
  additionalSearchParameters,
});

dynamicWidgets

Available as of Typesense Server v0.25.0.rc12

This dynamicWidgets widget works out of the box with no additional changes, but if you want to control the order in which these facets are displayed in the UI Instantsearch expects a parameter called renderingContent to be set.

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "xyz",
    nodes: [
      {
        host: "localhost",
        port: "8108",
        path: "/",
        protocol: "http",
      },
    ],
  },
  renderingContent: {
    // <<===== Add this, only if you want to control the order of the widgets displayed by dynamicWidgets
    facetOrdering: {
      facets: {
        order: ["size", "brand"], // <<===== Change this as needed
      },
    },
  },
  additionalSearchParameters,
});

Read more about all available options for renderingContent in Algolia's documentation here.

Special characters in field names / values

Available as of typesense-instantsearch-adapter 2.7.0-2

  • 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:

    const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
      server: {
        apiKey: "xyz",
        nodes: [
          {
            host: "localhost",
            port: "8108",
            path: "/",
            protocol: "http",
          },
        ],
      },
      facetableFieldsWithSpecialCharacters: ["brand"], // <======= Add string fields that have colons in their values here, to aid in parsing
      additionalSearchParameters,
    });
  • If any numeric field names in your documents have special characters like >, <, = (for eg, let's say there's a field called { price>discount: 3.0 }) then you would need to add a parameter like below when instantiating the adapter:

    const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
      server: {
        apiKey: "xyz",
        nodes: [
          {
            host: "localhost",
            port: "8108",
            path: "/",
            protocol: "http",
          },
        ],
      },
      facetableFieldsWithSpecialCharacters: ["price>discount"], // // <======= Add numeric fields that have >, < or = in their names, to aid in parsing
      additionalSearchParameters,
    });

Setting facet_by options

Available as of typesense-instantsearch-adapter 2.8.0-1 and Typesense Server v0.26.0.rc25

The facet_by parameter is managed by InstantSearch internally when you use the various filter widgets.

But 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:

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "xyz",
    nodes: [
      {
        host: "localhost",
        port: "8108",
        path: "/",
        protocol: "http",
      },
    ],
  },
  facetByOptions: {
    brand: "(sort_by: _alpha:asc)",
    category: "(sort_by: _alpha:desc)",
  }, // <======= Add any facet_by parameter as a key value pair. Don't forget the surrounding parantheses in the value.
  collectionSpecificFacetByOptions: {
    collection1: {
      brand: "(sort_by: _alpha:desc)",
    },
  }, // <======= 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.
  additionalSearchParameters,
});

Note that for sorting in refinementLists, in addition to sorting on the Typesense Server-side, you'd also need to pass the sortBy parameter to the refinementList widget to also sort the results appropriately on the client-side.

Setting filter_by options

Available as of typesense-instantsearch-adapter 2.8.0-5

The filter_by parameter is managed by InstantSearch internally when you use the various filter widgets.

By default, the adapter uses exact filtering (filter_by: field:=value) when sending the queries to Typesense. If 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:

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "xyz",
    nodes: [
      {
        host: "localhost",
        port: "8108",
        path: "/",
        protocol: "http",
      },
    ],
  },
  filterByOptions: {
    brand: { exactMatch: false }, // <========== Add this to do non-exact word-level filtering
    category: { exactMatch: false },
  },
  collectionSpecificFilterByOptions: {
    collection1: {
      brand: { exactMatch: false },
    },
  }, // <======= 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.
  additionalSearchParameters,
});

Disabling overrides for certain sorts

Available as of typesense-instantsearch-adapter 2.9.0-0

Here's a way to disable overrides / curation rules, when users select a particular sort order:

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "xyz",
    nodes: [
      {
        host: "localhost",
        port: "8108",
        path: "/",
        protocol: "http",
      },
    ],
  },
  sortByOptions: {
    "field1:desc,field2:desc": { enable_overrides: false }, // <========== Add this to disable sorting when this particular Typesense `sort_by` string is generated by the sortBy widget
  },
  collectionSpecificSortByOptions: {
    collection2: {
      "field1:desc,field2:desc": { enable_overrides: false },
    },
  }, // <======= 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.
  additionalSearchParameters,
});

If 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.

Grouped Hits

Available as of typesense-instantsearch-adapter 2.7.1-4

By 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.

If you'd like to preserve the groups, you want to set flattenGroupedHits: false when instantiating the adapter.

This 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.

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "xyz",
    nodes: [
      {
        host: "localhost",
        port: "8108",
        path: "/",
        protocol: "http",
      },
    ],
  },
  flattenGroupedHits: false, // <=======
  additionalSearchParameters,
});

Vector Search

Available as of typesense-instantsearch-adapter 2.7.0-3

The 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.

Here's a demo that you can run locally to see this in action: https://github.com/typesense/typesense-instantsearch-semantic-search-demo.

Here's how to do this in Instantsearch.js:

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "xyz",
    nodes: [
      {
        host: "localhost",
        port: "8108",
        path: "/",
        protocol: "http",
      },
    ],
  },
  additionalSearchParameters,
});
const searchClient = typesenseInstantsearchAdapter.searchClient;
const search = instantsearch({
  searchClient,
  indexName: "products",
  routing: true,
  async searchFunction(helper) {
    const query = helper.getQuery().query;
    const page = helper.getPage(); // Retrieve the current page
    const totalNearestNeighborsToFetch = 1000;

    if (query !== "") {
      // Get embedding for the query
      let response = await fetch(
        "http://localhost:8000/embedding?" + new URLSearchParams({ q: query }), // <=== Embedding API
      );

      let parsedResponse = await response.json();

      console.log(parsedResponse);

      // Send the embedding to Typesense to do a nearest neighbor search
      helper
        .setQueryParameter(
          "typesenseVectorQuery", // <=== Special parameter that only works in [email protected] and above
          `vectors:([${parsedResponse["embedding"].join(",")}], k:${totalNearestNeighborsToFetch})`,
        )
        .setPage(page)
        .search();
    } else {
      helper.setQueryParameter("typesenseVectorQuery", null).setPage(page).search();
    }
  },
});

Compatibility

Typesense Server typesense-instantsearch-adapter instantsearch.js react-instantsearch vue-instantsearch angular-instantsearch
>= v0.25.0 >= v2.7.1 >= 4.51 >= 6.39 >= 4.8 >= 4.4
>= v0.25.0.rc14 >= v2.7.0-1 >= 4.51 >= 6.39 >= 4.8 >= 4.4
>= v0.25.0.rc12 >= v2.6.0 >= 4.51 >= 6.39 >= 4.8 >= 4.4
>= v0.24 >= v2.5.0 >= 4.2.0 >= 6.0.0 >= 2.2.1 >= 3.0.0
>= v0.21 >= v2.0.0 >= 4.2.0 >= 6.0.0 >= 2.2.1 >= 3.0.0
>= v0.19 >= v1.0.0 >= 4.2.0 >= 6.0.0 >= 2.2.1 >= 3.0.0
>= v0.15 >= v0.3.0 >= 4.2.0 >= 6.0.0 >= 2.2.1 >= 3.0.0
>= v0.14 >= v0.2.0 >= 4.2.0 >= 6.0.0 >= 2.2.1 >= 3.0.0
>= v0.13 >= v0.1.0 >= 4.2.0 >= 6.0.0 >= 2.2.1 >= 3.0.0
>= v0.12 >= v0.0.4 >= 4.2.0 >= 6.0.0 >= 2.2.1 >= 3.0.0

If a particular version of the above libraries don't work with the adapter, please open a Github issue with details.

Widget Compatibility

This adapter works with all widgets in this list, except for the following:

  • queryRuleCustomData
  • queryRuleContext

Development

$ npm install
$ npm run typesenseServer
$ FORCE_REINDEX=true npm run indexTestData

$ npm link typesense-instantsearch-adapter
$ npm run testground

$ npm test

To release a new version, we use the np package:

$ npm install --global np
$ np

# Follow instructions that np shows you

Help

If you have any questions or run into any problems, please create a Github issue and we'll try our best to help.

© 2020-present Typesense, Inc.

typesense-instantsearch-adapter's People

Contributors

ashwinmram avatar dansnow avatar dependabot[bot] avatar faridmurzone avatar harisarang avatar jasonbosco avatar reinoldus avatar valerius21 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

typesense-instantsearch-adapter's Issues

Support for `<Configure filters={...} />`

Description

Hi there, I was wondering if the typesense adapter supports filters such as these. I can't see it in the documentation so I'm not too hopeful but it appears you support facetFilters according to issue #11 and not sure what else may be supported.

FacetFilters don't seem to support numeric boolean logic which is what I need to do for my usecase (e.g filter the data points by some numeric value, e.g cats < 12), so if there is another approach that I'm not seeing I'd be deeply appreciative of a point in the right direction.

Steps to reproduce

  1. Define some valid filters rule, e.g:
bedrooms: 4 TO 6 AND list_price: 60000 TO 70000
  1. Pass to react Configure web component:
<Configure filters="bedrooms: 4 TO 6 AND list_price: 60000 TO 70000"/>

Expected Behavior

I was hoping to see the filter rule applied to my data.

Actual Behavior

The filter rule is not applied to the data returned by the query.

Metadata

Typsense Version: 0.19

OS: Ubuntu 16.04

Is there a way to access the text_match score under the transformItems() when using Instantsearch + Typesense adapter

Hello!

I would like to know if this if there a way to access the text_match score under the transformItems() when using Instantsearch + Typesense adapter. The purpose of this to do additional client side sorting on the results. I can see in the returned XHR result that the text_match score is returned + document fields and values. If I do console.log(items) under the transformItems() function, there is no text_match score.

Sample code below.

instantsearch.widgets.hits({
	container: '#hits',
	transformItems(items) {
		items.map(function(item) {
			console.log(item.text_match); // returns undefined
		});
	}
});

Additional info:

Typsense Cloud Beta
Client: Instantsearch.js + Instantsearch Typesense adapter

Unable to initialize Typesense adapter with vue-instantsearch originating from CDN script tags

Description

Trying to set up an interface using Typesense + Instantsearch Adapter + Vue.js + vue-instantsearch, but the error is

Steps to reproduce

Import CDN links for Vue JS, IS Adapter, and VUE-IS

  • Follow guide as per algolia's vue js code sample
  • place cdn links on top
  • initialize vue div #app

Expected Behavior

Expected behavior is to show the search interface

Actual Behavior

Nothing shows up, and these errors can be noticed in console

[Vue warn]: Property or method "item" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
[Vue warn]: Error in render function: "TypeError: item is undefined"

Metadata

Latest typesense at time of writing

Mac OS X Big Sur (if relevant)

snippeting with multiple matches

In instantsearch.js we can use attributesToSnippet: ["content:50"] to return a part of the matched attribute. In cases where there are multiple matches (multiple occurrences of the keyword) in the same record, only one will be returned.
Is there a way to return all of them?

Does This Support React Native?

Want to go further with TypeSense on my App, would like to use it in conjunction with a Search UI Widget library, is this a possibility, or what are the alternatives if not?

🚀

Filter isssues

'filters' don't seem to be working for me. numericFilters generate an error. facetFilters do work.

example:
configure({ filters: 'price >= 200', numericFilters: ["price >= 500"], facetFilters: ['brand:lenovo','instock:true'], }),

error generated by numericFilters:
index.js:349 Uncaught Error: [Numeric filters] Can't switch from the advanced to the managed API. It is probably an error, if this is really what you want, you have to first clear the numeric filters.
at Function.SearchParameters.validate (index.js:349)
at SearchParameters.setQueryParameters (index.js:1362)
at Object.getWidgetSearchParameters (connectNumericMenu.js:161)
at index.js:83
at Array.reduce ()
at getLocalWidgetsSearchParameters (index.js:78)
at Object.init (index.js:297)
at InstantSearch.start (InstantSearch.js:431)
at Object.parcelRequire.src/app.js.jquery (app.js:259)

ais-configure filters not working as expected

Description

This adapter works like magic except I'm not sure how to apply filters that are not part of a refinement list but applied immediately. Is there any way to feed in some filters into the search client the way we do the additionalSearchParameters via the queryBy field?

Steps to reproduce

I used the following code and have configured the status as a facet but the filter is not getting applied.

public function getCollectionSchema(): array {
    return [
        'name' => 'reservations',
        'fields' => [
            // ...
            [
                'name' => 'hotel_id',
                'type' => 'int32',
                'facet' => true
            ],
            [
                'name' => 'status',
                'type' => 'string',
                'facet' => true
            ]
        ],
        'default_sorting_field' => 'hotel_id'
      ];
    }
<ais-instant-search
    :search-client="searchClient"
    index-name="reservations"
  >
    <ais-configure
          filters="hotel_id:1 AND status:checked_in OR status:due_out"
    ></ais-configure>
    // ...

Expected Behavior

I expect that the rendered list should be filtered to only display the status of checked_in and due_out.

Actual Behavior

No filters are being applied.

Metadata

Typsense Version: v0.17.0

OS: MacOS 10.15.7

How to add structured results for typesense?

Description

We are trying to add structured results like the extra information displayed apart from query results by search engines like Google, Bing and DuckDuckGo.

image

Steps to reproduce

We followed the documentation from Algolia for the InstantSearch for building this feature.
Documentation: https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/structured-results/js/?client=js
Demo Example: https://github.com/algolia/demo-structured-result

We have added two seperate collections to the typesense server as main_index and structured_index.
We modified the initialization of instantsearch client to accomodate the typesense server.

Problem

An error occurs stating Could not find a field name <field name> in the schema.

Any suggestions would be helpful in this regards.

Metadata

Typsense Version:
Latest
OS:
Ubuntu 20

Error when i import TypesenseInstantSearchAdapter

Description

Capture

i had install npm
npm install algoliasearch@3 angular-instantsearch@beta instantsearch.js@3 instantsearch.css
npm install --save-dev @types/algoliasearch
and add module NgAisModule

Steps to reproduce

Expected Behavior

Actual Behavior

Metadata

Typsense Version:

Does the adapter work with the hierarchicalMenu widget?

I just came across your adapter which looks quite promising. Before I dig deeper, does it support all the Algolia InstaSearchJS widgets, specially need to confirm the hierarchicalMenu widget?

UPDATE. Was just reviewing instant-meilisearch for comparison and they do not support searchable facets.
https://github.com/meilisearch/instant-meilisearch/issues/48

Does this adapter support that feature?
in fact, would this adapter be able to support all the InstantSearch features found in this demo? (my project is basically a clone of this one)
https://instantsearchjs.netlify.app/examples/e-commerce/search/

[Feature request] Customize snippeting

It would be useful if we could customize snippeting, for example show 2 lines before and 1 line after the match (total of 4 lines including the line containing the match). Or in terms of words instead of lines.

Error: 400 - Only upto 2 sort fields are allowed.

Description

Getting a console error with results not rendering when using sort_by with 3 values.
According to https://typesense.org/docs/0.17.0/api/ up to 3 sort fields can be specified but that throws an error in TypesenseInstantsearchAdapter.js.
We are using typesense server 0.19.0

Steps to reproduce

Configure sort to use 3 fields:

<SortBy
    defaultRefinement={`${indexName}/sort/poa:asc,model_weight:desc,price:asc`}
    items={[
        {label: 'Price (Lowest)', value: `${indexName}/sort/poa:asc,model_weight:desc,price:asc`},
        {label: 'Price (Highest)', value: `${indexName}/sort/poa:asc,model_weight:desc,price:desc`},
        
    ]}
/>

Expected Behavior

No example URL, but would expect results to be returned with the appropriate sort order

Actual Behavior

0 results, with console error(s):

Error: 400 - Only up to 2 sort fields are allowed. TypesenseInstantsearchAdapter.js:76

Metadata

Typsense Version: 1.0.0

OS: macOs 10.15.7

additionalSearchParameter -> 'q' or 'query' not respected

I want to try to issues:

  • Typesense should not display any hit without a given query. So the default search page should display the search box by default, display hits for a given query in the search field.
  • I want to pass a parameter with a text query to the search and the generated search form should display the query within the search form and display immediately the related hits.

This does not work:

    additionalSearchParameters: {
        queryBy: ts_settings["query_by"],
        filterBy: filterBy,
        q: "foo"
    },

I also tried query instead of q.

error 404 at TypesenseInstantsearchAdapter._validateTypesenseResult

hi,

typesense:0.21.0
"typesense-instantsearch-adapter": "^2.2.0"
"instantsearch.js": "^4.37.2",

linux ubuntu

i got algolia instantsearch installed ok, and work fine

when i want to use the adapter, i got this error in console and no hit appear on web view:

DevTools failed to load source map: Could not load content for https://cdn.jsdelivr.net/npm/instantsearch.production.min.js.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE TypesenseInstantsearchAdapter.js:76 Error: 404 - Not found. at TypesenseInstantsearchAdapter._validateTypesenseResult (TypesenseInstantsearchAdapter.js:173:1) at TypesenseInstantsearchAdapter.js:64:1 at Array.map (<anonymous>) at TypesenseInstantsearchAdapter._callee$ (TypesenseInstantsearchAdapter.js:63:1) at tryCatch (runtime.js:63:15) at Generator.invoke [as _invoke] (runtime.js:294:1) at Generator.next (runtime.js:119:1) at asyncGeneratorStep (asyncToGenerator.js:3:1) at _next (asyncToGenerator.js:25:1) _callee$ @ TypesenseInstantsearchAdapter.js:76 tryCatch @ runtime.js:63 invoke @ runtime.js:294 (anonymous) @ runtime.js:119 asyncGeneratorStep @ asyncToGenerator.js:3 _next @ asyncToGenerator.js:25 Promise.then (async) asyncGeneratorStep @ asyncToGenerator.js:13 _next @ asyncToGenerator.js:25 (anonymous) @ asyncToGenerator.js:32 (anonymous) @ asyncToGenerator.js:21 searchTypesenseAndAdapt @ TypesenseInstantsearchAdapter.js:88 search @ TypesenseInstantsearchAdapter.js:38 ./node_modules/algoliasearch-helper/src/algoliasearch.helper.js.AlgoliaSearchHelper._search @ algoliasearch.helper.js:1270 ./node_modules/algoliasearch-helper/src/algoliasearch.helper.js.AlgoliaSearchHelper.searchOnlyWithDerivedHelpers @ algoliasearch.helper.js:154 mainHelper.search @ InstantSearch.js:389 (anonymous) @ InstantSearch.js:108 (anonymous) @ defer.js:24 Promise.then (async) fn @ defer.js:16 start @ InstantSearch.js:464 ./themes/default-theme/assets/js/index.js @ index.js:46 __webpack_require__ @ bootstrap:19 ./themes/default-theme/assets/app.js @ app.js:11 __webpack_require__ @ bootstrap:19 (anonymous) @ bootstrap:83 (anonymous) @ bootstrap:83 TypesenseInstantsearchAdapter.js:173 Uncaught (in promise) Error: 404 - Not found. at TypesenseInstantsearchAdapter._validateTypesenseResult (TypesenseInstantsearchAdapter.js:173:1) at TypesenseInstantsearchAdapter.js:64:1 at Array.map (<anonymous>) at TypesenseInstantsearchAdapter._callee$ (TypesenseInstantsearchAdapter.js:63:1) at tryCatch (runtime.js:63:15) at Generator.invoke [as _invoke] (runtime.js:294:1) at Generator.next (runtime.js:119:1) at asyncGeneratorStep (asyncToGenerator.js:3:1) at _next (asyncToGenerator.js:25:1)

query undefined should be "*" as well

Description

If the query is undefined it should be interpreted as "*" instead of giving an error. This is also the instantsearch behavior

Expected Behavior

Consider undefined as "*"

Actual Behavior

Considered as undefined and results in an error

I'd suggest to change:

    Object.assign(typesenseSearchParams, {
      collection: this._adaptIndexName(instantsearchRequest.indexName),
      q: params.query === "" ? "*" : params.query,
      facet_by: [params.facets].flat().join(","),
      filter_by: this._adaptFilters(params.facetFilters, params.numericFilters),
      sort_by: adaptedSortBy || this.additionalSearchParameters.sortBy,
      max_facet_values: params.maxValuesPerFacet,
      page: (params.page || 0) + 1
    });

to

    Object.assign(typesenseSearchParams, {
      collection: this._adaptIndexName(instantsearchRequest.indexName),
      q: (params.query === "" || !params.query) ? "*" : params.query,
      facet_by: [params.facets].flat().join(","),
      filter_by: this._adaptFilters(params.facetFilters, params.numericFilters),
      sort_by: adaptedSortBy || this.additionalSearchParameters.sortBy,
      max_facet_values: params.maxValuesPerFacet,
      page: (params.page || 0) + 1
    });

highlight_fields causing them to be shown as 'undefined'

Description

highlight_fields causing them to be shown as 'undefined'

Steps to reproduce

if the field is not in queryBy: "description,concat" it's shown as undefined when there is a highlight.
in this case:
highlight_fields:"name,description,concat",

Typsense Version: 0.22.rc6
"typesense-js": "^0.14.0",
"typesense-instantsearch-adapter": "^2.0.1"

OS: linux ubuntu

note: earlier versions of the typesense js libraries were showing all these fields as undefined even if there was no highlight.

problem with get data in typesense

Description

I have a problem with use the lib with vue3, I use the js lib with vue2 and found.

Steps to reproduce

Old project
https://github.com/agucova/regulf-neo

New project
https://github.com/jonatasoli/regulf-neo-v3

Expected Behavior

The old project is found correct and list the result, but project with vue3 is raise error:
TypesenseInstantsearchAdapter.js?7ea0:76 Error: Request failed with HTTP code 401 | Server said: Forbidden - a valid x-typesense-api-key header must be sent.

Actual Behavior

Run the server and enter in home page, is found.

Old project:
npm start

new project:
npm serve

Metadata

Typsense Version:
0.11.0

OS:
Fedora 34

Using filter_by and other Typesense search parameters

Description

As the documentation says, it should be possible to specify additional search parameters. queryBy works, but filterBy doesn’t.

Steps to reproduce

I tried the following parameters:

additionalSearchParameters: {
queryBy: 'name',
filterBy: 'myfilter:0',
'filter_by': 'myfilter:0',
}

Expected Behavior

Filtered results

Actual Behavior

Unfiltered results

Metadata

Typsense Version:

OS:

Events

Is there any way to catch the response from TS server in browser as variable or something? I can't find it in Instantsearch.js
I mean - any time the search return hits I need somehow to get those and lets say send some analytics or something else

Regex lookbehind in SearchRequestAdapter.js not supported in Safari

Description

We're seeing the following error in Safari: SyntaxError: Invalid regular expression: invalid group specifier name. The responsible code appears to be the lookbehind in the regex on line 38 which is unsupported by Safari:

new RegExp("(?<!:):(?!:)")

Steps to reproduce

I don't have a public test URL at the moment, but all that's necessary is to load our (complex) search which uses multiple Algolia InstantSearch widgets.

Expected Behavior

On page load, initial search results or results modified by query string.

Actual Behavior

On page load we see multiple instances of the error, and no results.

Metadata

Typsense Version: 0.3.4

OS: macOs 11.1 / iOS

sort_by not working with instantsearch widget

Hello,

is it correct that sorting is not working like the way algolia works?
For the sortby widget they using replicas, is there a way I can edit the url with a self made widget?

Typesense does not support cross-field ORs at the moment. The adapter could not OR values between these field

Description

Typesense does not support cross-field ORs at the moment. The adapter could not OR values between these field

This error is from SearchRequestAdapter.js. The error itself is self-descriptive, I just want to know why in this example, https://showcase-nextjs-typesense-ecommerce-store.vercel.app/ ,it is completely to use cross-field ORs.

error

Steps to reproduce

{
  "name": "sections",
  "fields": [
    {
      "name": "organization",
      "type": "string",
      "facet": true,
      "optional": false,
      "index": true
    },
    {
      "name": "course_code",
      "type": "string",
      "facet": false,
      "optional": false,
      "index": true
    },
    {
      "name": "course_title",
      "type": "string",
      "facet": false,
      "optional": false,
      "index": true
    },
    {
      "name": "students",
      "type": "string[]",
      "facet": false,
      "optional": false,
      "index": true
    },
    {
      "name": "instructors",
      "type": "string[]",
      "facet": false,
      "optional": false,
      "index": true
    },
    {
      "name": "num_students",
      "type": "int32",
      "facet": false,
      "optional": false,
      "index": true
    },
    {
      "name": "num_instructors",
      "type": "int32",
      "facet": false,
      "optional": false,
      "index": true
    },
    {
      "name": "created_at",
      "type": "string",
      "facet": false,
      "optional": false,
      "index": true
    },
    {
      "name": "updated_at",
      "type": "string",
      "facet": false,
      "optional": false,
      "index": true
    }
  ],
  "default_sorting_field": ""
}

This is the schema.

The error should not happen, just as https://showcase-nextjs-typesense-ecommerce-store.vercel.app/

Metadata

Typsense Version: 2.2.0

OS: ubuntu

[Feature request] Excluding a facet

Description

It would be nice to be able to use the negative faceting from typesense v0.21

Instantsearch supports it by adding a "-" in front of the to be refined value.

Some time ago I created a pull request (more a draft than done): #50

Would be great if we could support this somehow

algolia/instantsearch#1232

Adapater + Nuxt + SSR doesn't not seem work nicely

Description

There seem to be issues with ssr and this adapter, I built this sandbox to show the problem: https://codesandbox.io/s/dazzling-lichterman-zlo9y?file=/pages/search.vue

It includes pretty much the code from the docs.

Steps to reproduce

  1. Go to the sandbox homepage, click on search -> everything works
  2. Reload the page on /search: You'll get the following error:
 ERROR  [params.facets].flat is not a function                        06:05:48

  at SearchRequestAdapter._buildSearchParameters (node_modules/typesense-instantsearch-adapter/lib/SearchRequestAdapter.js:166:35)
  at node_modules/typesense-instantsearch-adapter/lib/SearchRequestAdapter.js:203:32
  at Array.map (<anonymous>)
  at SearchRequestAdapter._callee$ (node_modules/typesense-instantsearch-adapter/lib/SearchRequestAdapter.js:202:55)
  at tryCatch (node_modules/regenerator-runtime/runtime.js:63:40)
  at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:293:22)
  at Generator.next (node_modules/regenerator-runtime/runtime.js:118:21)
  at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
  at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)
  at node_modules/@babel/runtime/helpers/asyncToGenerator.js:32:7
  at new Promise (<anonymous>)
  at SearchRequestAdapter.<anonymous> (node_modules/@babel/runtime/helpers/asyncToGenerator.js:21:12)
  at SearchRequestAdapter.request (node_modules/typesense-instantsearch-adapter/lib/SearchRequestAdapter.js:218:25)
  at TypesenseInstantsearchAdapter._callee3$ (node_modules/typesense-instantsearch-adapter/lib/TypesenseInstantsearchAdapter.js:149:39)
  at tryCatch (node_modules/regenerator-runtime/runtime.js:63:40)
  at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:293:22)

In my own project the initial SSR state is loaded, but once I change any parameter the following happens:

{
  "searches": [
    {
      "query_by": "name,brand",
      "num_typos": 1,
      "sort_by": "",
      "highlight_full_fields": "name,brand",
      "collection": "public_products",
      "facet_by": "",
      "filter_by": "",
      "page": 1
    },
    {
      "query_by": "name,brand",
      "num_typos": 1,
      "sort_by": "",
      "highlight_full_fields": "name,brand",
      "collection": "public_products",
      "q": "water",
      "facet_by": "marketing_claims,category_functional,approved",
      "filter_by": "category_functional:=[Moisturizers] && approved:=[true]",
      "max_facet_values": 25,
      "page": 1
    },
    {
      "query_by": "name,brand",
      "num_typos": 1,
      "sort_by": "",
      "highlight_full_fields": "name,brand",
      "collection": "public_products",
      "q": "water",
      "facet_by": "approved",
      "filter_by": "category_functional:=[Moisturizers]",
      "max_facet_values": 25,
      "page": 1,
      "per_page": 1
    }
  ]
}

I get the following response:

{
  "results": [
    {
      "code": 400,
      "error": "Parameter `q` is required."
    },
    {
      "facet_counts": [
        {
          "counts": [

          ],
          "field_name": ".......",
          "stats": {}
        },
        {
          "counts": [
            {
              "count": 5,
              "highlighted": "...",
              "value": "..."
            }
          ],
          "field_name": "...........",
          "stats": {}
        },
        {
          "counts": [
            {
              "count": 5,
              "highlighted": "true",
              "value": "true"
            }
          ],
          "field_name": "....",
          "stats": {}
        }
      ],
      "found": 5,
      "hits": [
        {
          "document": {
            "brand": "....",
            "category_functional": [
              "...."
            ],
            "frequency": 0,
            "id": "19877",
            "ingredients_by_id": [
            ],
            "marketing_claims": [
              "...."
            ],
            "name": ".....", 
             [...]
          },
          "highlights": [
            {
              "field": "name",
              "matched_tokens": [
                "Water"
              ],
              "snippet": ".....",
              "value": "......"
            }
          ],
          "text_match": 16907875
        },
[...]
      ],
      "out_of": 35919,
      "page": 1,
      "request_params": {
        "collection_name": "public_products",
        "per_page": 1,
        "q": "water"
      },
      "search_time_ms": 1
    }
  ]
}

As if the q parameters wasn't applied properly. Unfortunately, I do not even get to this state with the sandbox, but maybe the issues are related

Metadata

Copied apikey etc. from the books example: https://books-search.typesense.org/

refinementList with ::

I have some strings in facet values like Lvl::Itermediate

When selected in refinementList XHR request is like filter_by=facet_attribute:%3D[Lvl] (missing ::Itermediate) and no results found

What I need to do?

Holding backspace does not remove first character in refinementList search field

Description

When using a searchable refinementList and using search inside the facet widget to filter results, the first character is not cleared if holding backspace, removing characters one at a time works though.

Example from: https://recipe-search.typesense.org/
ts_facet

Steps to reproduce

Go to https://recipe-search.typesense.org/
Search for something
Type something in the filter ingredients facet search
Hold backspace to remove facet search string completely

instant search around lat lng to typesense geo search

Description

I am currently attempting to use the <ais-config> attribute aroundLatLng to perform a search based on an the radius around an object's lattitude and longitude.

Steps to reproduce

My ais-config tag looks like:

<ais-configure
        :aroundLatLng="aroundLatLng"
        :hits-per-page.camel="10"
/>

Where the prop aroundLatLng is

'_geoloc:(48.90615915923891, 2.3435897727061175, 5.1 km)'

Expected Behavior

I was expecting to see the results within a 5.1 km radius from the lat and lng entered

Actual Behavior

I got:
image

Metadata

Typsense Version: 0.21.0

OS: macOS ver 11.4

InstantSearch and Hits components not found.

Description

For React-InstantSearch, does we need to import a specific modue to use the components and Hits? Because I encounter the error components not found when i call them in my application.

Steps to reproduce

Expected Behavior

Actual Behavior

Metadata

Typsense Version:

OS: windows 10

React Instantsearch SortBy not sorting beyond default sorting field

Description

When using with React Instantsearch, sorting beyond the default sort with the SortBy widget is not sorting. The defaultRefinement prop is required and the widget has different syntax than instantsearch js.

Steps to reproduce

             <SortBy
                defaultRefinement="products"
                items={[
                  { label: 'Rating - Best', value: 'products' },
                  { label: 'Price - Lowest', value: "products/sort/price:asc"},
                  { label: 'Newest', value: 'products/sort/createdAt:asc'},
                ]}
              />

Expected Behavior

Selecting Price - lowest or Newest would sort by the field price or createdAt

Actual Behavior

Only sorting by the default schema sorting works.

Alternates tried:

             <SortBy
                items={[
                  { label: 'Rating - Best', value: 'products' },
                  { label: 'Price - Lowest', value: "products/sort/price:asc"},
                  { label: 'Newest', value: 'products/sort/createdAt:asc'},
                ]}
              />
             <SortBy
                defaultRefinement="products"
                items={[
                  { label: 'Rating - Best', value: 'products' },
                  { label: 'Price - Lowest', value: "sort/price:asc"},
                  { label: 'Newest', value: 'sort/createdAt:asc'},
                ]}
              />
             <SortBy
                defaultRefinement="products"
                items={[
                  { label: 'Rating - Best', value: 'products' },
                  { label: 'Price - Lowest', value: "/sort/price:asc"},
                  { label: 'Newest', value: '/sort/createdAt:asc'},
                ]}
              />
             <SortBy
                defaultRefinement="products"
                items={[
                  { label: 'Rating - Best', value: 'products' },
                  { label: 'Price - Lowest', value: "price:asc"},
                  { label: 'Newest', value: 'createdAt:asc'},
                ]}
              />

Metadata

"react": "16.12.0",
"typesense": "^0.11.1",
"typesense-instantsearch-adapter": "^1.0.0"

Mac OS

Typescript definitions missing fields

Description

I'm very new to Typescript, so maybe I'm doing something wrong here. But it seems that the type definition for additionalSearchParameters is missing the fields groupBy and groupLimit. Also, numTypos can actually accept a list of numbers in the URL param, but its type definition is only a single number.

I also needed to @ts-ignore this line:

const search = instantsearch({
    // @ts-ignore
    searchClient: searchClient,
    ....
});

Because Typesense's searchClient is defined only as an object, but the definitions in instantsearch (which I think they only recently added?) require it to actually have the right fields.

Really appreciate the work in adding type definitions though, I'm brand new to Typescript but already enjoying it! Thanks!

Workaround

Other than the @ts-ignore line, I used this code to amend the type definitions:

declare module 'typesense-instantsearch-adapter' {
  interface BaseSearchParameters {
    groupBy?: string
    groupLimit?: number
  }

Metadata

typesense-instantsearch-adapter Package Version: 2.3.0
typesense Package Version: 1.1.3
instantsearch.js Package Version: 4.37.3

Query params in autocomplete

Description

Hi, I am trying to implement autocomplete using algolia's autocomplete and typesense. These are two links that I gotten the code snippets from
https://codesandbox.io/s/github/algolia/autocomplete/tree/next/examples/react-renderer?file=/src/Autocomplete.tsx
https://www.algolia.com/doc/ui-libraries/autocomplete/guides/creating-a-renderer/

Current code snippet: https://gist.github.com/JyYong93/0d0d5e31d1468378e2a7160cc6e5bb0d

The autocomplete is able to fetch from typesense on the initial render but no matter how I tried to update the query subsequently, the autocomplete does not send another request to typesense. I did check the network requests in console but the current search looks something like
[{
"query_by": "name",
"sort_by": "",
"highlight_full_fields": "name",
"collection": "posts",
"q": "*",
"facet_by": "",
"filter_by": "",
"page": 1,
"per_page": 5
}]

The query params did not update so am I missing something obvious in the current code?

I am using

typesense-instantsearch-adapter: 1.2.2
next: 11.0.1
@algolia/autocomplete-js: 1.2.0

Hope someone can point me in the right direction. Thank you.

Steps to reproduce

Using the current code snippet, only initial data is fetched from typesense but does not request from typesense again when the query is updated.

Expected Behavior

Query params does update.
[{
"query_by": "name",
"sort_by": "",
"highlight_full_fields": "name",
"collection": "posts",
"q": "newQuery",
"facet_by": "",
"filter_by": "",
"page": 1,
"per_page": 5
}]

Actual Behavior

Query params does not update.
[{
"query_by": "name",
"sort_by": "",
"highlight_full_fields": "name",
"collection": "posts",
"q": "*",
"facet_by": "",
"filter_by": "",
"page": 1,
"per_page": 5
}]

Metadata

Typesense Version:
typesense-instantsearch-adapter: 1.2.2
typesense: v0.20.0

Disjunctive facets

Description

I am not able to get disjunctive facets (https://community.algolia.com/algoliasearch-helper-js/reference.html#disjunctive-facets) to work

Steps to reproduce

This is the code I am using with the books mapping:

search.addWidgets([
    configure({
        "disjunctiveFacets": [
            "authors_facet"
        ]}),

Expected Behavior

I would like to filter on the authors and then when I select author A , with disjunctiveFacet being authors_facet, I would expect that the facet only displays authors that have written a book together with author A

Actual Behavior

All authors are being shown in the facet

With a facet being added to the disjunctiveFacet array, users should be able to find a book that has the categories romance AND action. Currently selecting romance and action shows either romance OR action books

additionalSearchParameters filterBy is not passed into the request

Description

additionalSearchParameters filterBy is not passed into the request

Steps to reproduce

Starting with the sample code in https://github.com/typesense/typesense-instantsearch-demo/blob/master/src/app.js, I added an additionalSearchParameters filterBy like so:

  additionalSearchParameters: {
    queryBy: 'searchName',
    filterBy: 'type:=f',
  },

Expected Behavior

I'd expect that this is passed into my typesense endpoint

Actual Behavior

The actual request looks like this however:

https://<my-endpoint>/collections/trails/documents/search?query_by=searchName&filter_by=&highlight_full_fields=searchName&q=*&facet_by=&page=1

i.e. filter_by is not set.

Metadata

Typsense Version:
"typesense": "^0.7.0"
"typesense-instantsearch-adapter": "0.3.0"
algoliasearch/3.32.0/algoliasearchLite.min.js
npm/[email protected]

OS:
Win10

Dynamically load additional search parameters / query by

I'd like to start off by saying a big THANK YOU :) for making it so simple to swap out the awesome Instantsearch library with Typesense via this adaptor. I was praying there was such a solution last week and yesterday I discovered both Typesense and your adaptor. I was afraid that most of the money earned through my app when the record size grows will be paid to Algolia, but now that is no longer a concern!

Description

I am using Vue Instantsearch and have defined the search client in my root Vue component. The problem I am facing is that the queryBy search parameters will change for each model and I'm not sure how to swap this out dynamically.

More Details

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: "api-key", 
    nodes: [
      {
        host: "hostname",
        port: "443",
        protocol: "https"
      }
    ]
  },
  
  additionalSearchParameters: {
    queryBy: "full_name,last_name,first_name"
  }
});
const searchClient = typesenseInstantsearchAdapter.searchClient;

const app = new Vue({
   el: '#app',

   data() {
     return {
       searchClient
     };
   },

On my model specific page I call the component as below:

  <ais-instant-search
    :search-client="searchClient"
    index-name="guests"
  >

My challenge is if I define a universal searchClient like I previously did with Algolia's search client I am unsure how to dynamically define the query by search parameters. With Algolia this was not required.

I tried definiing all the fields across all my models on the global searchClient but when the document does not have that search field it throws an error, which makes sense of course.

I'd appreciate some help on this!

Metadata

Typsense Version: v0.17.0 / Typesense Cloud

OS: MacOS Catalina 10.15.7

How to prune a field while displaying it?

Description

We modified the demo(s) to the following. I believe it is pretty self explanatory.
additionalSearchParameters: {
//queryBy: 'text',
queryBy: 'title,description,text',
},

instantsearch.widgets.configure({
hitsPerPage: 8,
attributesToSnippet: ['text:200']
}),
instantsearch.widgets.hits({
container: '#hits',
templates: {
item: <div> <div class="hit-name"><a href={{url}}> {{#helpers.highlight}}{ "attribute": "title" }{{/helpers.highlight}} </a> <p>{{#helpers.snippet}}{ "attribute": "description" }{{/helpers.snippet}}</p> <p>{{#helpers.snippet}}{ "attribute": "text" }{{/helpers.snippet}}</p> </div> <div class="hit-authors"> {{ category }} </div> </div>,
},

Our "text" field is body of wikipedia article, so its fairly big. When I search, I am able to highlight the search term in in SERP but the surrounding text is only 50-70 characters long. Am i doing something wrong?

Eg: If I search for "startup" in my dataset, I am getting response
in the Silicon Valley startup scene, with products based
instead of
OpenAI’s GPT-3 is a hot new machine learning model that can perform what look like miracles. It’s backed by some of the biggest names in the Silicon Valley startup scene, with products based on it raising VC money at a blistering pace

(https://doxa.substack.com/p/ai-has-a-walled-garden-problem)

Steps to reproduce

Add instantsearch.widgets.configure() and use text field for snippeting.

Expected Behavior

Expect to see longer snippet.
OpenAI’s GPT-3 is a hot new machine learning model that can perform what look like miracles. It’s backed by some of the biggest names in the Silicon Valley startup scene, with products based on it raising VC money at a blistering pace

Actual Behavior

Metadata

Typsense Version:
Latest version
OS:

Routing does not work with connectInfiniteHits()

Description

Trying to implement infinite scroll as from this example.
https://codesandbox.io/s/github/algolia/doc-code-samples/tree/master/InstantSearch.js/infinite-scroll

Everything works but routing does not update URL when setting route: true.
Works as intended on the Algolia example but not in typesense-instantsearch-adapter.

I'm guessing it has something to do with using connectInfiniteHits() to create a custom infiniteHits() function?

Steps to reproduce

Use code from https://codesandbox.io/s/github/algolia/doc-code-samples/tree/master/InstantSearch.js/infinite-scroll to implement infinite scroll with typesense-instantsearch-adapter, set routing: true, scroll down.

Expected Behavior

URL should update page number when loading new items.

Actual Behavior

URL does not update.

Metadata

Typesense: v0.18.0
typesense-instantsearch-adapter: v0.3.4

Multiple requests made for refinement list

Description

Faceted search not updating proper counts after clicking a refinement list.

Steps to reproduce

Added html markup as per instructions and added refinementList widgets inside addWidgets(). If you can't reproduce then I will add full steps to reproduce.

Expected Behavior

A single request with proper response/handling.

Actual Behavior

After page load the initial request and result looks fine and html gets populated as expected. However, when clicking a value on a refinementList then 2 requests are sent. Clicking a value on another refinementList then 3 requests are sent. The request parameters differ and the results are all over the place.

Metadata

Typesense Version: 0.15.0
Typesense.js Version: 0.7.0
Typesense instantsearch adapter Version: 0.3.0
Instantsearch.js Version: 4.5.0

OS: windows

Multi-index search -> queryby can not be individually chosen

Description

I would like to implement a multi index search using the following component from instantsearch: https://www.algolia.com/doc/api-reference/widgets/index-widget/vue/

The issue is: It only works if both indexes share the same attribute you want to query on, if you want to query e.g. name in index A and body in index B then you'd have to instantiate two search clients which would also result in two requests to the server.

It would be great if we could use to overwrite queryBy or add something like this to additonalSearchParameters:

      additionalSearchParameters: {
        "index A": {queryBy: this.queryBy,},
        "index B": {queryBy: this.queryBy,}
      },

Steps to reproduce

The following snippet should help to build a sample app

<template>
  <ais-instant-search :search-client="searchClient" :index-name="indexName">
    <b-form-input v-model="query" placeholder="Search"></b-form-input>
    <search-debounced-search-box :query="query"></search-debounced-search-box>
    <ais-index index-name="index_2">
      <ais-hits v-if="query || initialResults">
        <template slot-scope="{ items }">
          <div
            v-for="item in items"
            :key="item.objectID"
            class="pointer py-3"
            @click="query = undefined"
          >
            <slot :item="item"</slot>
          </div>
        </template>
      </ais-hits>
    </ais-index>
    <ais-hits v-if="query || initialResults">
      <template slot-scope="{ items }">
        <div
          v-for="item in items"
          :key="item.objectID"
          class="pointer py-3"
          @click="query = undefined"
        >
          <slot :item="item"></slot>
        </div>
      </template>
    </ais-hits>
  </ais-instant-search>
</template>

<script>
import {
  AisInstantSearch,
  AisHits,
  AisIndex
} from 'vue-instantsearch'

import TypesenseInstantSearchAdapter from 'typesense-instantsearch-adapter'
import SearchDebouncedSearchBox from '@/components/search/search-debounced-search-box'

export default {
  components: {
    SearchDebouncedSearchBox,
    AisInstantSearch,
    AisHits,
    AisIndex
  },
  props: {
    indexName: {
      type: String,
      default() {
        return 'x'
      },
    },
    queryBy: {
      type: String,
      default() {
        return 'name'
      },
    },
    initialResults: {
      type: Boolean,
      default() {
        return false
      },
    },
  },
  data() {
    const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
      server: {
        apiKey: 'xxxxxxxxxxxxxxxxxxxx', // Be sure to use the search-only-api-key
        nodes: [
          {
            host: 'xxxxxxxxxxxxxxxxxxxx',
            port: '443',
            protocol: 'https',
          },
        ],
      },
      // The following parameters are directly passed to Typesense's search API endpoint.
      //  So you can pass any parameters supported by the search endpoint below.
      //  queryBy is required.
      additionalSearchParameters: {
        queryBy: this.queryBy,
      },
    })
    const searchClient = typesenseInstantsearchAdapter.searchClient
    // searchClient.widget.configure()
    return {
      searchClient,
      query: this.initialQuery,
    }
  },
}
</script>

Expected Behavior

I can set the queryBy-parameter for each index separately

Actual Behavior

Querying only works if both indexes share the attribute e.g: "name"

sortBy and IS routing

What is the best way to use sortBy and instantsearch.js routing?
What I'm trying is to have urls like &sort_by=price:desc filtering results and preselect sortBy widget option

npm install throws an error on Windows

Description

running npm install throws an error (on Windows?)

Steps to reproduce

npm install

Expected Behavior

npm to complete and node_modules folder to appear

Actual Behavior

image

I see nothing of interest in the mentioned log file.
Other projects are updating installing fine
I tried npm cache clean --force
I updated to the last node and npm
nothing seems to work

Metadata

OS: Windows 10 Pro 20H@ 19042.685

Support for operator

Description

Algolia's RefinementList supports operator which lets you select if you want to do and or or operation. Seems like it's not supported by the adapter yet. Specifying operator="and" is disregarded.

Typsense Version: 0.19.0

Is this compatible with Algolia Autocomplete?

As far as my understanding goes, Instant Search and Autocomplete are treated as different things in Algolia's Instant Search documentation. My current implementation in Algolia uses the Autocomplete feature and i am trying to migrate it to Typesense, but Algolia's documentation is making me a bit confused if Autocomplete is part of instant search or not

Algolia hitsPerPage is not honored

Description

Using typesense with the instantsearch.js and trying to limit the number of results displayed per page

Steps to reproduce

instantsearch.widgets.configure({
hitsPerPage: 4,
enablePersonalization: true,
});

Expected Behavior

Display 4 items

Actual Behavior

displays 10 items per page

Metadata

Typsense Version: 0.20.0

OS: linux

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.