Using a query string to filter results by _tags

instantsearch
javascript

#1

I have a refinement list that uses a field successfully. All my hits also come back with keywords and _tags associated with that individual hit. I would like to make each tag clickable so it appends something to the url and filters based on that tag. I can’t use a refinement list since Im localizing the list to the hits. I tried to use stateToRoute and routeToState, but that doesn’t seem to do anything. Here is my config if it helps get the talk started:

      const search = instantsearch({
      indexName: 'Sample_portal',
      searchParameters: {
    	  facets: ['_tags']
      },
      searchClient,routing: {
        stateMapping: {
          stateToRoute({query, refinementList, page}) {
            return {
              query: query,
              // we use the character ~ as it is one that is rarely present in data and renders well in URLs
              brands:
                refinementList &&
                refinementList.DocumentType &&
                refinementList.DocumentType.join('~'),
    		  tags:
                refinementList &&
                refinementList.Keywords &&
                refinementList.Keywords.join('~'),
              page: page
            };
          },
          routeToState({query, brands, tags, page}) {
            return {
              query: query,
              refinementList: {
    			Keywords: tags && tags.split('~'),
    			DocumentType: brands && brands.split('~')
              },
              page: page
            };
          }
        }
      }
    });

#2

Hi mdonahue,

I am Pierre a Software Engineer working at Algolia.

I understand that you would like to use the hidden _tags with stateMapping/stateToRoute. I have setup a little demo using this functionality: https://codesandbox.io/embed/6nw79y366r

Would you mind to update the code with your case, so that we could better help you find an answer?

Let me know how it goes and if you have more questions.
Best regards,


#3

Excellent, thanks for taking the case! I have forked your example here: https://codesandbox.io/s/5m26zv9x1k
I have some formatting to clean up in or index import process, but if you look at:

[“Hexter, Kathryn”,“Keating, W Dennis”,“Jones, Mittie Davis”,“Mikelbank, Brian”,“Veres, Michael”,“Huang, Joyce”]

There is a tag “rent.” I’d love to be able to click that and allow the filter to be applied in addition to the brand refinement list. I’m sure you can see my attempt in the routing config of the js file. Im hoping thr url would be something like this (notice the tags parameter), but open to any suggestions: https://5m26zv9x1k.codesandbox.io/?brands=scholar&tags=rent


#4

_tags is the legacy facet-like feature and it does not behave like a regular facet. What I would suggest is to find an alternative like:

  1. Directly use facet filters and refinementList instead.
  2. In order to make it work using _tags: you would need a refinementList for each of the facets that is relevant and then convert from _tags to proper facet filters.

#5

Option one sounds good. I can use Keywords instead. In my index I have configured it to now include the Keywords field which contains abn array in a string:

keywords

I have adjusted our working sample to route basted on the keywords parameter. Do I need special formatting on that field maybe?


#6

I cleaned up the data a bit, and formatted keywords to be better array. When I some changes to our sandbox, it changes the url to https://codesandbox.io/s/pjpw0mr10x.
I tried coding the refinement list into the url like sohttps://pjpw0mr10x.codesandbox.io/?refinementList%5Bkeywords%5D%5B0%5D=Gas. That didnt work either. I prefer the routing method if possible (but cant get it to cooperate) https://pjpw0mr10x.codesandbox.io/?keywords=Gas


#7

Also, building a refinement into the url doesn’t work either: https://pjpw0mr10x.codesandbox.io/?refinementList[keywords][0]=Gas.


#8

I’ve looked at your Codesandbox and I implemented a refinement list on keywords like you wanted it.
State is driven by widgets so it’s important you have them mounted on the page to be able to see their effect on the state.

Of course, you can always hide it by adding display: none.
Another, maybe cleaner, but more complicated approach, would be to implement a custom refinement list with an no-op render method. (cf. docs).
This will remove the performance overhead of rendering unnecessary DOM.
But the simplicity of adding display: none on the default widgets makes it the best solution for me.

I hope this helps. Have a nice day!


#9

Thanks Youcef, that’s a step in the right direction. In your solution, if you look at the listed hit results on the page, many of the keywords that show on each hit are not in the refinement listing.

However, I think I have a working solution. Looks like as long as the refinement widget is on the page, I can use the url routing even for keywords not pulled back. So Im adding an onclick to change the url appropriately and refresh the page.

You can see my demo here: https://codesandbox.io/s/326y00p3o5