Searchkick: Right way to index and perform autocomplete

Created on 22 Nov 2016  路  3Comments  路  Source: ankane/searchkick

Which is the right way to perform an autocomplete?

https://github.com/ankane/searchkick#instant-search--autocomplete
OR
https://github.com/ankane/searchkick/blob/2e6c82a16a542d250922dfb345631b3ba428cd77/test/inheritance_test.rb#L43

For indexing, shouldn't it be autocomplete: [:name] instead of word_start: [:name]?

question

Most helpful comment

My guess is you need to use misspellings: false. Also, to help with debugging queries and mappings, you can use the recently added:

Product.search("something", debug: true)

All 3 comments

The readme has the latest instructions. Those tests are for a legacy option.

@ankane I found that autocomplete: true performs the way I would like but word_start does not.

For me if I search for a Product for number "pm07" then I only want that product returned, I don't want "pm01" or "pm03" returned. I was only able to get this to work by using autocomplete:true but I can't figure out why.

If we look at what's created for word_start we find:
Mapping
"product_number" : { "type" : "keyword", "fields" : { "analyzed" : { "type" : "text" }, "word_start" : { "type" : "text", "analyzer" : "searchkick_word_start_index" } }, "ignore_above" : 256 },
Analyzer
searchkick_word_start_index: { type: "custom", tokenizer: "standard", filter: ["lowercase", "asciifolding", "searchkick_edge_ngram"] },

searchkick_edge_ngram filter
searchkick_edge_ngram: { type: "edgeNGram", min_gram: 1, max_gram: 50 },

If we look at what's created for autocomplete we find:

Mapping
"product_number" : { "type" : "keyword", "fields" : { "analyzed" : { "type" : "text" }, "autocomplete" : { "type" : "text", "analyzer" : "searchkick_autocomplete_index" } }, "ignore_above" : 256 }

Analyzer
"searchkick_autocomplete_index" : { "filter" : ["lowercase","asciifolding"], "type" : "custom", "tokenizer" : "searchkick_autocomplete_ngram" },

Tokenizer
tokenizer: { searchkick_autocomplete_ngram: { type: "edgeNGram", min_gram: 1, max_gram: 50 } }

So I think both word_start and autcomplete use lowercase, asciifolding and edgeNGram.

The difference I think comes in the search query and the use of autocomplete: true. So with word_start we can simply use:

Product.search "pm07"

whereas with autocomplete we have:

Product.search "pm07", autocomplete: true

which I think then uses the following code:
if options[:autocomplete] payload = { multi_match: { fields: fields, query: term, analyzer: "searchkick_autocomplete_search" } }

searchkick_autocomplete_search: { type: "custom", tokenizer: "keyword", filter: ["lowercase", "asciifolding"] },

At this point in time I can't figure out what payload code is called/used for word_start and how it differs to that used by autocomplete.

My guess is you need to use misspellings: false. Also, to help with debugging queries and mappings, you can use the recently added:

Product.search("something", debug: true)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

matthewmoss picture matthewmoss  路  4Comments

ankane picture ankane  路  5Comments

tomajask picture tomajask  路  4Comments

yurgon picture yurgon  路  4Comments

jiujiubad picture jiujiubad  路  4Comments