So let's say I enter the text "Ebook" for searching and get the following results:
Ebook for Rails
Elastic Ebook
Booking for ebook.
Now I select "Elastic Ebook" from the list. Let's say that several other users input Ebook for searching and most of them select "Elastic Ebook" from the list. This clearly indicates the popularity for Elastic Ebook for the key word "Ebook". Hence in further searches, I would want Elastic Ebook to have higher priority and appear at the top.
Elastic Ebook
Ebook for Rails
Booking for an ebook.
Is there any way to achieve this.
My code document.rb :
require 'elasticsearch/model'
class Document < ApplicationRecord
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
belongs_to :user
Document.import force: true
def self.search(query)
__elasticsearch__.search({
query: {
multi_match: {
query: query,
fields: ['name^10', 'service'],
fuzziness: "AUTO"
}
}
})
end
settings index: {
"number_of_shards": 1,
analysis: {
analyzer: {
edge_ngram_analyzer: { type: "custom", tokenizer: "standard", filter:
["lowercase", "edge_ngram_filter", "stop", "kstem" ] },
}
},
filter: {
edge_ngram_filter: { type: "edgeNGram", min_gram: "3",
max_gram: "20" }
}
} do
mapping do
indexes :name, type: "string", analyzer: "edge_ngram_analyzer"
indexes :service, type: "string", analyzer: "edge_ngram_analyzer"
end
end
end
search controller code:
def search
if params[:query].nil?
@documents = []
else
@documents = Document.search params[:query]
end
end
There is no simple solution for this. Elasticsearch does not know what your users choose in the application.
In the simplest approach it would have to be your responsibility to tell elasticesearch what is popular (just after user searched and clicked on one of the results from the list), and store this information in your documents by updating them. Technically updating means deleting and inserting the document again but it can be done with Update API and scripts.
Having this, you can use function_score
queries to search with boosting-by-popularity:
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "Rental",
"fields": [ "name"]
}
},
"field_value_factor": {
"field": "popularity",
"modifier": "..."
}
}
}
}
where popularity
is the field you update.
It is also possible to store the information about popluratity in separate documents and extend the query to combine these two sources of information.
There are also plugins for Learning to Rank integration but I've never used them so it's hard to tell how complicated it is to integrate.