typesense / typesense-instantsearch-adapter

A JS adapter library to build rich search interfaces with Typesense and InstantSearch.js
MIT License
414 stars 64 forks source link

HOT INFO - Dynamic widget works in typesense 0.25.0.rc12 #150

Open pixelkoduje opened 1 year ago

pixelkoduje commented 1 year ago

Hello, with the release of typesense 0.25.0.rc12, facet_by: ["*"] works, so the dynamic widget also works! Well, almost, because you probably need to make a slight correction. It executes the query correctly by adding dynamicWidget, but the typesense adapter apparently misinterprets - because it doesn't show 0 number of attributes - and it fetches all of them nicely. Can action be expected on this? Beautiful thanks!

QUERY: image

RESPONSE: image

It works ! However, apparently the typesense adapter misinterprets and shows 0. image However, I think, looking at the lack of bugs, that it's a small step for you, and a big one for the environment! heh

jasonbosco commented 1 year ago

Thanks for testing this out!

I tried to take a quick stab at this, but I'm not able to get the DynamicWidgets widget to display, even with an Algolia index... I haven't used this widget before, so may be I'm missing something obvious in the configuration.

Could you help me with this? Could you follow the instructions here setup DynamicWidgets using Algolia's demo data and share the working project in a github repo once you get it to work?

I can then update the adapter as needed to make it work in Typesense.

pixelkoduje commented 1 year ago
import Head from 'next/head';
import React from 'react';
import TypesenseInstantSearchAdapter from "typesense-instantsearch-adapter";
import { renderToString } from 'react-dom/server';
import {
  DynamicWidgets,
  InstantSearch,
  Hits,
  RefinementList,
  ToggleRefinement,
  InstantSearchSSRProvider,
} from 'react-instantsearch-hooks-web';
import { getServerState } from 'react-instantsearch-hooks-server';
import { createInstantSearchRouterNext } from 'react-instantsearch-hooks-router-nextjs';
import singletonRouter from 'next/router';
import {assembleTypesenseServerConfig} from '../lib/utils'
import { Hit } from "../components/Hit";

const TYPESENSE_SERVER_CONFIG = assembleTypesenseServerConfig()
const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
  server: TYPESENSE_SERVER_CONFIG,
  additionalSearchParameters: {
    // 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.
    query_by: 'name,categories,description',
    // facet_by: "*"
    // query_by_weights: '4,2,1',
    // // num_typos: 1,
    // typo_tokens_threshold: 1,
    // group_by: "categories",
    // groupLimit: 1
    // pinnedHits: "23:2"
  },
});

export default function HomePage({ serverState, url }) {
  return (
    <InstantSearchSSRProvider {...serverState}>
      <Head>
        <title>React InstantSearch Hooks - Next.js</title>
      </Head>

      <InstantSearch
        searchClient={typesenseInstantsearchAdapter.searchClient}
        indexName="products"
        routing={{
          router: createInstantSearchRouterNext({
            serverUrl: url,
            singletonRouter
            }),

        }}
      >
      <DynamicWidgets facets={["*"]} fallbackComponent={FallbackComponent}></DynamicWidgets>
      <ToggleRefinement
                  className="mt-5"
                  attribute="free_shipping"
                  label="Free Shipping"
                  value={true}
      />
      <Hits hitComponent={Hit}/>
      </InstantSearch>
    </InstantSearchSSRProvider>
  );
}

function FallbackComponent({ attribute }) {
  return (
    <Panel header={attribute}>
      <RefinementList attribute={attribute} />
    </Panel>
  );
}

export async function getServerSideProps({ req }) {
    const protocol = req.headers.referer?.split('://')[0] || 'http';
    const url = `${protocol}://${req.headers.host}${req.url}`;

    const serverState = await getServerState(<HomePage url={url} />, {
      renderToString,
    });

    return {
      props: {
        serverState,
        url,
      },
    };
  };

Example from next.js

You must have server 0.25.0.rc12 from docker hub installed of course. https://hub.docker.com/r/typesense/typesense/tags

And I'm working on data from: https://github.com/typesense/showcase-nextjs-typesense-ecommerce-store All you have to do is run this script and insert the appropriate data and it will work.

pixelkoduje commented 1 year ago

When you click on the toggle after loading, you will see that it sends the appropriate data to typesense and shows no errors. Instead it's just an empty array of arguments all the time in dynamicWidget. But that's a good sign because it's downloading everything - but apparently the adapter isn't getting data from a good place, hence there are 0 items.

pixelkoduje commented 1 year ago

Because of the error, it's a minor thing. As the whole thing works, it does not show these attributes, without showing errors of some kind. please take a look :)

jasonbosco commented 1 year ago

I meant to say, could you get the DynamicWidgets working with Algolia, instead of Typesense, in a demo project? I tried the instructions in their official guide and even there the Dynamic Widgets are being rendered as blank...

So if you can give me a project where their instructions render the DynamicWidgets widget in the UI when talking to Algolia (not Typesense), I can then use that as reference to get it to work with Typesense.

pixelkoduje commented 1 year ago

https://www.algolia.com/doc/api-reference/widgets/dynamic-facets/react/?client=widget#examples https://instantsearchjs.netlify.app/stories/react/?path=/story/dynamicwidgets--default ...

pixelkoduje commented 1 year ago

Everything is in the examples.. Just type algolia react dynamicwidget in google.

grinkus-adapt commented 1 year ago

@jasonbosco here's a working CodeSandbox example of DynamicWidgets working with Algolia.

I'm not too familiar with the component myself, but I think the idea is that you define different widgets as children of the DynamicWidgets and they get rendered only when there are results that the widgets would affect. For example try typing in "dog" or "lego" in the SearchBox in the CodeSandbox example. For "lego" there's categories and brands displayed, for "dog" only categories, and if the searchbox is left empty then there's a few more filters/widgets.

pixelkoduje commented 1 year ago

There is no philosophy here. Instantsearch makes a query and I get an array of items which is passed to the dynamicwidget. Will you be updating it? Because it's really a little thing.

pixelkoduje commented 1 year ago

I am asking because I am creating a project that will be in many countries and the number of all guys will be even 150+. And at one time, for example, 10. Hence, it needs a dynamicwidget. And it seems to me that it is nice to be able to boast of such a service.

jasonbosco commented 1 year ago

@grinkus-adapt Thank you for sharing that working CodeSandbox. I was able to identify what config changes needed to be done for those widgets to show up.

I've pushed out v2.6.0-0 of the adapter that adds support for dynamicWidgets, when used with Typesense Server v0.25.0.rc12.

Here are instructions on how to configure the adapter to make this work: ~https://github.com/typesense/typesense-instantsearch-adapter/tree/1016e7a86d67322078183ef4f7dd31c1d2260633#dynamicwidgets~

See update here: https://github.com/typesense/typesense-instantsearch-adapter/issues/150#issuecomment-1442434057

pixelkoduje commented 1 year ago

Thank you on behalf of myself and others. Very quick response. 5+ :) @jasonbosco

pixelkoduje commented 1 year ago

image

It doesn't make sense ... I might as well create a variable. const guy = ["hello", "world"] ... I expected it to work. If I set up in Dynamicwidget ["*"], it is to provide currently downloaded from API guy. I gave examples of what the result of downloading from TypeSense looks like. What is done now is completely meaningless. I might as well enter: guy: { Order: ["dick"], // << ====== change this as Needed }, ` And it will also display it.

pixelkoduje commented 1 year ago

Modering is just an addition that shows how to sort what comes with API. image

By adding to Dynamicwidgets ["*'] API returns all available guys, in the question given. And this should be available in attributes.

pixelkoduje commented 1 year ago

Gives an example: By selecting, for example, HierarchicalMenu - the categories change. Typesense returns only available facets. By which DynamicWidget gets the correct facet attributes. And with every change, they can change too. For example, in the category of jackets - there is no "shoe size" attribute. Which is why it won't show up because the api doesn't return it. Throwing in rigidly makes no sense at all.

image

jasonbosco commented 1 year ago

@pixelkoduje I appreciate the good feedback (but not the tone of the feedback).

jasonbosco commented 1 year ago

I've pushed out an update in v2.6.0-1 that doesn't require you to set renderingContent. But if you want to configure the display order, then you can optionally configure it: https://github.com/typesense/typesense-instantsearch-adapter/tree/ts-server-0.25-changes#dynamicwidgets

pixelkoduje commented 1 year ago

@jasonbosco You are doing a good job, I tested and it works as expected. (I tested the main functionality - if I find any problems with sorting, etc. I will let you know) - But what interested me the most works. Thank you!

jasonbosco commented 1 year ago

Great, thank you confirming and thank you again for the great feedback!