meilisearch / meilisearch-js-plugins

The search client to use Meilisearch with InstantSearch.
https://www.meilisearch.com
MIT License
471 stars 57 forks source link

Add disjunctive facet search #884

Closed bidoubiwa closed 1 year ago

bidoubiwa commented 1 year ago

disjunctiveFacetSearch changes how we handle multiple facet filters. See this spec to understand.

To understand better the following explanation, lets consider that we have two facets fields:

Current behavior

When performing a search requiring that color is red and genres is drama, instant-meilisearch is going to perform ONE search requests with the following filters:

Only search request:

[["genres=drama"], ["color=red"]]

Unfortunately, this is not the expected behavior when using facets on most websites.

Disjunctive facet search

Using disjunctive facet search, we make as many requests as their are different facets filters.

For example, in our case above, we should have made 3 requests.

Search requests:

first request

[["genres:Adventure"], ["color:red"]],

Second request:

[["color:red"]],

Third request:

[["genres:Adventure"]],

The good news is that instantsearch provides us with the required requests. For example, if we ask for color blue and genres Adventure on a movie index, instantsearch provides us with the following objects:

( objects were reduced for readability )

[
  {
    "indexName": "movies",
    "params": {
      "facetFilters": [["genres:Adventure"], ["color:blue"]],
      "facets": ["genres","color"],
      "maxValuesPerFacet": 10,
      "query": "",
      "tagFilters": ""
    }
  },
  {
    "indexName": "movies",
    "params": {
      "facetFilters": [["color:blue"]],
      "facets": "genres",
      "hitsPerPage": 0,
      "maxValuesPerFacet": 10,
      "page": 0,
      "query": ""
    }
  },
  {
    "indexName": "movies",
    "params": {
      "facetFilters": [["genres:Adventure"]],
      "facets": "color",
      "hitsPerPage": 0,
      "maxValuesPerFacet": 10,
      "page": 0,
      "query": ""
    }
  },
]

We can then make a search request per element provided by instantsearch. Some elements are important to take into account:

Corner cases

engel-m commented 1 year ago

I am not sure if the issue I am having is related to this, but for me a weird thing is that I am setting up my project exactly like the code in this example:

https://codesandbox.io/s/ms-is-mese9?fontsize=14&hidenavigation=1&theme=dark&file=/index.html:952-1057

But for me, disjunctive facetting does not work at all. When I select a facet, it filters correctly, but then removes all other options (which do have a hit count also), as if it were a non disjunctive facet. I can not figure out why the same code does not behave like in the example above.

Am I missing something in configuring the index maybe? Should a facet that is used with disjunctive always be stored as an array in the index f.e.? Or is this an issue with refinementList in the specific instant-meilisearch version (I am using 0.10.1)?

bidoubiwa commented 1 year ago

Hey @engel-m, are you using the current release of instant-meilisearch or this branch ? #888

engel-m commented 1 year ago

@bidoubiwa Update on this:

I have the problem with both branches.

I found out I was not able to get disjunctive facets to work because I had not configured keepZeroFacets to be set to true.

If I do, I can select multiple options for a facet without the rest disappearing. This would mean that when selecting a facet value, the result count of the other selectable values goes to zero.

bidoubiwa commented 1 year ago

Could you show me your configuration? keepZeroFacets is not working currently with multi-index/disjunctive facet search. I'm working on fixing that issue. But nonetheless, the disjunctive should at least react the same way as on the gifs in the PR.

Btw, did you set your operators on your refinement list to and, as disjunctive only works with or ?

engel-m commented 1 year ago

@bidoubiwa I tried every possible configuration combination there is, but with the exception of keepZeroFacets set to true and operator or , I can not even select multiple values for a facet. Once refined, the rest disappears.

Basically, I have the same problem as in this issue: https://github.com/meilisearch/instant-meilisearch/issues/789

But when I install your #888 branch it doesn't change anything for me, same issue as #789

bidoubiwa commented 1 year ago

Sorry, I may not have been clear. keepZeroFacets=true does not work currently on the multi-index search. See the todo at the end of the body of the PR https://github.com/meilisearch/instant-meilisearch/pull/888

I'm working on the fix :)

bidoubiwa commented 1 year ago

The beta it is released on npm :) Here

Could you try it ?

pix2D commented 1 year ago

Is there a way to force a particular facet is always taken into account? For example what if we always want to make sure the correct genre was returned, but then for other facets we don't care that much and they can fallback to less and less specific filters?

Our specific example is that we have a diets facet in our recipes app, and obviously if someone selects vegetarian we do not want to fall back to non-vegetarian recipes. But for all other facets it's fine.

bidoubiwa commented 1 year ago

Can the and operator solve your issue? Otherwise I would use the searchFunction or a wrapper around the instantMeilisearch.search method to change the value of facets/filters. This guide might help you

jeremylynch commented 1 year ago

Are we close to getting this one merged in?

bidoubiwa commented 1 year ago

It is available in a beta version. You can try it out already :) See release notes on how to try it.

It is up to date with the current latest release so trying it should not break anything

We are waiting for additional feedbacks to merge it

MoustafaElsaghier commented 1 year ago

can the same be done through APIs?

sparkison commented 1 year ago

Works great! šŸŽ‰ thanks so much for implementing this feature šŸ™

bidoubiwa commented 1 year ago

Hey @MoustafaElsaghier, the multi-index search in the API is in consideration. We are discussing it here. Could you provide the reason why it would be useful to you there?

Thanks a lot for your feedback šŸ™

MoustafaElsaghier commented 1 year ago

Hello @bidoubiwa, I'm looking for the disjunctive feature to be in API not a multi-index search

to be more clear, I need the disjunctive feature in the same index search same as the main GitHub issue in this thread

jeremylynch commented 1 year ago

Hi @bidoubiwa are we close to having this feature out of beta?

bidoubiwa commented 1 year ago

Hey! The release is planned around the 13th February

bidoubiwa commented 1 year ago

Released on the latest dist tag on npm :)