Using multiple virtual Menus for disjunctive faceting

In a recent question about disjunctive facteing, @haroen recommended this approach to join widgets using OR:

Yes, because the default operation to apply between different widgets is AND, if you wanted that behaviour you could use multiple virtual Menus.

Is there an example of this approach somewhere? I’m intercepting this.state.refinementList in onSearchStateChange, and using it to build an OR-joined filters parameter string used in a <Configure /> component, which doesn’t seem to be enough to override the default behavior or returned hits.

Hi Jed!

I have no experience with Instantsearch’s Virtual Menus yet.

Would this guide help? https://community.algolia.com/react-instantsearch/guide/Virtual_widgets.html

Thanks @adrien.joly1! Unfortunately, it doesn’t cover anything related. There doesn’t seem to be a lot of documentation around the interaction between faceting widgets.

Hey Jed,

This makes sense, indeed between the different widgets, you will always have “and”, because of the way our filters work. The way to work around that is making indeed sure that you do the disjunctive faceting yourself in a custom made widget, which will then be “and” to the rest of the page.

Can you give a codeSandbox of what you have so far? We have an example here.

Thanks, @haroen, does this help?

So what you should make now from that (and sorry for answering late) is:

  1. make versions of RefinementList which don’t actually refine

You can do this by going to the source in the “components” directory, and taking those

  1. have those communicate to their parent

  2. create a <Configure/> with the filters you calculate from that.

Hope that helps!

1 Like

After implementing this, I can say it’s a pretty bad solution. I really wish Algolia would have better support for disjunctive filtering across refinementLists.

This is what’s wrong with your approach:

  1. Making a version of RefinementList that doesn’t refine is pretty simple using connectRefinementList, but there’s no good support for managing the isRefined state for each facet value. i.e., setting the filter through Configure has no effect on the items a refinementList has.
  2. The facet values returned for each refinementList are still filtered across lists. For example you have two lists Color [red, blue, green] and Size [small, medium, large]. With two items in the index, a large red and a small green, if you filter for red you will not see the small facet in your Size list. With disjunctive filters this is not the behavior you want.
  3. You can no longer rely on your InstantSearch's searchState to handle routing.

Hey Guido,

I think you are right, this is indeed not a trivial topic at all. Luckily since you want OR between OR, it’s in theory fixable. The reason we haven’t invested further in this is because OR between AND isn’t possible with Algolia, neither is OR between facets of different types.

Can you show what you have now in a sandbox?

Unfortunately I abandoned that branch once I realized how difficult it would be to handle routing. But I basically did what you suggested, with a couple of refinmentLists that don’t call refine and instead call a function that manages the state one layer up, and renders that state in a Configure.

What I ended up doing that works, but might not work for everyone, is update my index to include a new property which is a list of the facets I want to filter on. So for my example above, instead of faceting on Size and Color, I have a new property on my search objects that’s a list of those properties.

This will only work if the values you intend to facet are distinct across all the facets you want to OR across.