# Как правильно построить autocomplete для товаров в магазине

**URL:** <https://discuss.elastic.co/t/autocomplete/202887>\
**Category:** Вопросы на русском языке\
**Created:** [October 9, 2019, 5:25pm UTC](https://discuss.elastic.co/t/autocomplete/202887 "2019-10-09T17:25:23Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alexey\_Kapitonov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/alexey_kapitonov/32/47533_2.png) [@Alexey\_Kapitonov](https://discuss.elastic.co/u/Alexey_Kapitonov)\
**Post date:** [October 9, 2019, 5:25pm UTC](https://discuss.elastic.co/t/autocomplete/202887/1 "2019-10-09T17:25:23Z")

</div>

Добрый день, подскажите, как правильно построить autocomplete для товаров в магазине,  
чтобы при подаче на входе iPhone предлагались не товары а вариации продолжения фразы:  
iphone 6s  
iphone 11 16Gb  
как тут [http://joxi.ru/DmBPz8acJ3Ev5A](http://joxi.ru/DmBPz8acJ3Ev5A)

на данный момент удалось настроить, только продолжение вводимой фразы, при этом если не начат ввод нового слова, предложений не выводится

**форма данных в индексе:**

```auto
      "body" => array:6 [
        "title" => "Холодильник ATLANT ХМ 4423-060 N"
        "title_tags" => array:5 [
          0 => "Холодильник"
          1 => "Холодильник ATLANT"
          2 => "Холодильник ATLANT ХМ"
          3 => "Холодильник ATLANT ХМ 4423-060"
          4 => "Холодильник ATLANT ХМ 4423-060 N"
        ]
        "title_keyword" => " Холодильник ATLANT ХМ 4423-060 N "
        "description" => "линейка: PREMIUM 44 Serie, ШхВхГ: 59.50х196.50х62.50 см, класс энергопотребления A, общий объем 320 л, No Frost"
        "category" => ""
        "brand" => "ATLANT"
      ]
      "index" => "product_index_11232assd5453"
      "type" => "product_11232assd5453"
      "id" => 2942

```

**mapping**

```auto
    '_source' => [
                'enabled' => true
            ],
            'properties' => [
                'title' => [
                    'type' => 'text',
                    'analyzer' => 'a_analyzer',
                    'search_analyzer' => 'f_analyzer'
                ],
                'title_keyword' => [
                    'type' => 'text',
                    'analyzer' => 'trigram',
                    'search_analyzer' => 'trigram'
                ],
                'description' => [
                    'type' => 'text',
                    'analyzer' => 'a_analyzer',
                    'search_analyzer' => 'f_analyzer'
                ],
                'category' => [
                    'type' => 'text',
                    "index" => false
                ],
                'brand' => [
                    'type' => 'text',
                    'analyzer' => 'a_analyzer',
                    'search_analyzer' => 'f_analyzer'
                ],

                'title_tags' => [
                    'type' => 'text',
                    'analyzer' => 'a_analyzer',
                    'search_analyzer' => 'f_analyzer',
    // "payloads" => false
                ],

            ]

```

**index\_settings**

```auto
    'analysis' => [
                'filter' => [
                    'autocomplete_filter' => [
                        'type' => 'edge_ngram',
                        'min_gram' => '1',
                        'max_gram' => '15'
                    ],
                    'russian_stop' => [
                        'type' => 'stop',
                        'stopwords' => '_russian_'
                    ],
                    'russian_stemmer' => [
                        'type' => 'stemmer',
                        'language' => 'russian'
                    ],
                    'my_synonyms' => [
                        'type' => 'synonym',
                        'synonyms' => [
                            'купить => телефон',
                            'телефон => смартфон',
                        ]
                    ],

                    "my_phonetic_cyrillic" => [
                        "type" => "phonetic",
                        "encoder" => "beider_morse",
                        "rule_type" => "approx",
                        "name_type" => "generic",
                        "languageset" => ["cyrillic"]
                    ],
                    "my_phonetic_english" => [
                        "type" => "phonetic",
                        "encoder" => "beider_morse",
                        "rule_type" => "approx",
                        "name_type" => "generic",
                        "languageset" => ["english"]
                    ]
                ],
                'analyzer' => [
                    "trigram" => [
                        "type" => "custom",
                        "tokenizer" => "standard",
                        "filter" => ["lowercase", "shingle"]
                    ],
                    "rus_en_key_analyzer" => [
                      "char_filter" =>[
                          "rus_en_key",
                          "en_rus_key"
                      ],
                        "tokenizer" => "standard",
                        "token_filter" => ["lowercase"]
                    ],

                    "reverse" => [
                        "type" => "custom",
                        "tokenizer" => "standard",
                        "filter" => ["lowercase", "reverse"]
                    ],
                    'a_analyzer' => [
                        'type' => 'custom',
                        'tokenizer' => 'standard',
                        "char_filter" =>[
                            "rus_en_key",
                            "en_rus_key"
                        ],
                        'filter' => ['lowercase', 'autocomplete_filter']
                    ],
                    'f_analyzer' => [
                        'type' => 'custom',
                        'tokenizer' => 'standard',
                        "char_filter" =>[
                            "rus_en_key",
                            "en_rus_key"
                        ],
                        'filter' => [
                            "lowercase",
                            "russian_stemmer",
                            "russian_stop",
                            "my_phonetic_english",
                            "my_phonetic_cyrillic"
                        ]
                    ],
                    'reuters' => [
                        'type' => 'custom',
                        'tokenizer' => 'standard',
                        'filter' => ['lowercase', 'stop', 'kstem']
                    ],

                ],
                "char_filter" =>[
                    "rus_en_key" =>[
                        "type" => "mapping",
                        "mappings" => [
                            "a => ф",
                            "b => и",
                            "c => с",
                            "d => в",
                            "e => у",
                            "f => а",
                           
                        ]
                    ],

                    "en_rus_key" =>[
                        "type" => "mapping",
                        "mappings" => [
                            "ф => a",
                            "и => b",
                            "с => c",
                            "в => d",
                            "у => e",
                            "а => f",

                        ]
                    ]
                ]
            ]

```

---

<div class="post-metadata">

**Author:** ![Alexey\_Kapitonov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/alexey_kapitonov/32/47533_2.png) [@Alexey\_Kapitonov](https://discuss.elastic.co/u/Alexey_Kapitonov)\
**Post date:** [October 9, 2019, 5:26pm UTC](https://discuss.elastic.co/t/autocomplete/202887/2 "2019-10-09T17:26:00Z")

</div>

**search запрос**

```auto
    'query' => [
                        "multi_match" => [
                            "query" => $searchText,
                            "fields" => ['brand^4','title_keyword^3','title'],
                            "type" => "bool_prefix",
                            "boost" => 1,
                            'fuzziness' => 2,
                            "prefix_length" => 1,
                            "max_expansions" => 100,
                        ],
                    ],
                    "suggest" => [
                        "text" => $searchText,
                        "autocomplete-suggest-1" => [
                            "phrase" => [
                                "field" => "title_keyword",
                                "size" => 10, // количество предложений в выдаче
                                "gram_size" => 3,
                                "confidence" => 0.0,
                                "direct_generator" => [
                                    [
                                        "field" => "title_keyword",
                                        "suggest_mode" => "always",
                                        "min_word_length" => 0,
                                        "prefix_length" => 2,
                                    ],
                                ],
                                "highlight" => [
                                    "pre_tag" => "<b>",
                                    "post_tag" => "</b>"
                                ]
                            ],
                        ],
                        "my-suggest-1" => [
                            "text" => $searchText,
                            "term" => [
                                "field" => "title_keyword"
                            ]
                        ],

                    ]

```

---

<div class="post-metadata">

**Author:** ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)\
**Post date:** [October 9, 2019, 6:02pm UTC](https://discuss.elastic.co/t/autocomplete/202887/3 "2019-10-09T18:02:37Z")

</div>

А чем [Completion Suggester](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters.html#completion-suggester) не подходит?

---

<div class="post-metadata">

**Author:** ![Alexey\_Kapitonov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/alexey_kapitonov/32/47533_2.png) [@Alexey\_Kapitonov](https://discuss.elastic.co/u/Alexey_Kapitonov)\
**Post date:** [October 9, 2019, 6:07pm UTC](https://discuss.elastic.co/t/autocomplete/202887/4 "2019-10-09T18:07:57Z")

</div>

дело в том, что по сути поиск выполняется по title,  
если полностью title туда скормить , то вывод будет полного title и эффет добавления одного слова пропадает.  
пробовал положить в suggester данные  
"title\_tags" : [  
0 =\> "Холодильник"  
1 =\> "Холодильник ATLANT"  
2 =\> "Холодильник ATLANT ХМ"  
3 =\> "Холодильник ATLANT ХМ 4423-060"  
4 =\> "Холодильник ATLANT ХМ 4423-060 N"  
]  
но требуемого эфета не получилось

---

<div class="post-metadata">

**Author:** ![Alexey\_Kapitonov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/alexey_kapitonov/32/47533_2.png) [@Alexey\_Kapitonov](https://discuss.elastic.co/u/Alexey_Kapitonov)\
**Post date:** [October 9, 2019, 6:10pm UTC](https://discuss.elastic.co/t/autocomplete/202887/5 "2019-10-09T18:10:25Z")

</div>

так же были попытки с такой структурой:  
{  
"suggest" : [  
{  
"input": "Холодильник",  
"weight" : 5  
},  
{  
"input": "Холодильник ATLANT",  
"weight" : 4  
},  
{  
"input": "Холодильник ATLANT ХМ",  
"weight" : 3  
},  
{  
"input": "Холодильник ATLANT ХМ 4423-060",  
"weight" : 2  
},  
{  
"input": "Холодильник ATLANT ХМ 4423-060 N",  
"weight" : 1  
}  
]  
}  
тоже безрезультатно,

подскажите, какую именно структуру данных выбрать для suggestions?

---

<div class="post-metadata">

**Author:** ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)\
**Post date:** [October 9, 2019, 6:18pm UTC](https://discuss.elastic.co/t/autocomplete/202887/6 "2019-10-09T18:18:41Z")

</div>

Я бы как-то так начал:

```auto

DELETE test

PUT test
{
    "mappings": {
        "properties" : {
            "suggest" : {
                "type" : "completion"
            },
            "title" : {
                "type": "keyword"
            }
        }
    }
}

PUT test/_doc/1?refresh
{
    "suggest" : {
        "input": ["Холодильник ATLANT ХМ 4423-060 N"],
        "weight" : 34
    }
}

PUT test/_doc/2?refresh
{
    "suggest" : {
        "input": ["Холодильник INDESIT DS 4160 S"],
        "weight" : 34
    }
}

POST test/_search?pretty
{
    "suggest": {
        "test-suggest" : {
            "prefix" : "Холодильник", 
            "completion" : { 
                "field" : "suggest" 
            }
        }
    }
}

POST test/_search?pretty
{
    "suggest": {
        "test-suggest" : {
            "prefix" : "Холодильник I", 
            "completion" : { 
                "field" : "suggest" 
            }
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [November 6, 2019, 6:18pm UTC](https://discuss.elastic.co/t/autocomplete/202887/7 "2019-11-06T18:18:41Z")

</div>

Closed on November 6, 2019, 6:18pm UTC

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
