appbaseio / reactivesearch

Search UI components for React and Vue
https://opensource.appbase.io/reactivesearch
Apache License 2.0
4.89k stars 470 forks source link

Boosting by popularity, or script_score in elasticsearch query #487

Closed dioscuroi closed 5 years ago

dioscuroi commented 5 years ago

Issue Type: enhancement

Platform: Web

Description: Is there a way to use the "script_score" feature in the elasticsearch query to boost search results by popularity? The reference can be found here. Thanks!

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#function-script-score

Reactivesearch version: 2.7.0

dioscuroi commented 5 years ago

I solved the problem by using the "customQuery" field. Below is my code.

<DataSearch
  componentId="searchbar"
  autosuggest={true}
  showClear={true}
  autoFocus
  customQuery={
    function(value, props) {
      return {
        function_score: {
          query: {
            match: { name: value }
          },
          script_score : {
            script : {
              source: "Math.log(2 + doc['popularity'].value)"
            }
          }
        }
      }
    }
  }
/>
siddharthlatest commented 5 years ago

We can also support this at the library level. DataSearch and CategorySearch components can have a prop called popularityField (which has to have a Numeric mapping). When present and valid, the query is transformed to a function_score type query.

Instead of a script_score function, we will support the field_value_factor function.

{
    "query": {
        "function_score": {
            "query": { ... original query ...},   // this is the query the component was generating so far.
            "field_value_factor": {
                "field": "likes",   // this is the user specified popularity field
                "modifier": "log1p",// this smoothens the score (read more: https://www.elastic.co/guide/en/elasticsearch/guide/current/boosting-by-popularity.html#_modifier)
                "missing": 1        // when field has missing value, treat this as default value.
            }
        }
    }
}

As @dioscuroi shared in the above example, a user can always override this behavior by specifying a customQuery, but this gives a very quick way to add custom popularity (and allows to support the popularity use-case via a GUI in Dejavu, appbase.io dashboard, etc.)

dioscuroi commented 5 years ago

Yes, it will be awesome if popularity is supported at the library level. Thank you for adding it to the milestone. Please keep me updated when it is done! 😁

stonesthatwhisper commented 1 year ago

We can also support this at the library level. DataSearch and CategorySearch components can have a prop called popularityField (which has to have a Numeric mapping). When present and valid, the query is transformed to a function_score type query.

Is this actually implemented? So I was trying to use customQuery to do something similar, but I need to obtain the "original query" generated, but could not find a way to get it. Is this at all possible?

Instead of a script_score function, we will support the field_value_factor function.

{
    "query": {
        "function_score": {
            "query": { ... original query ...},   // this is the query the component was generating so far.
            "field_value_factor": {
                "field": "likes",   // this is the user specified popularity field
                "modifier": "log1p",// this smoothens the score (read more: https://www.elastic.co/guide/en/elasticsearch/guide/current/boosting-by-popularity.html#_modifier)
                "missing": 1        // when field has missing value, treat this as default value.
            }
        }
    }
}