Correspondência de produtos usando o Elasticsearch para o serviço de monitoramento de preços dos concorrentes

Em 2017, surgiu a idéia de desenvolver um serviço de monitoramento de preços dos concorrentes. Sua característica distintiva de outros serviços similares era a função da correspondência automática diária de mercadorias. Aparentemente, devido à quase completa falta de informações sobre como fazer isso, os serviços de monitoramento de preços ofereciam apenas a possibilidade de comparação manual pelos próprios clientes ou pelos operadores de serviços com um preço de 0,2 a 1 rublo por fato de comparação. A situação real com, por exemplo, 10 sites e 20.000 produtos em cada um, exige inevitavelmente a automação do processo, pois a correspondência manual já é muito longa e cara.

A abordagem da correspondência automática será descrita abaixo usando um exemplo de várias farmácias concorrentes usando a tecnologia Elaticsearch .

Descrição do ambiente


  1. SO: Windows 10
  2. Base: Elaticsearch 6.2
  3. Cliente para solicitações: Postman 6.2

Configurando o Elaticsearch


Configuração do mapeador e analisador de campo do produto em uma solicitação

PUT http://localhost:9200/app { "mappings": { "product": { "properties": { "name": { "type": "text", "analyzer": "name_analyzer" #        }, "manufacturer": { "type": "text" }, "city_id": { "type": "integer" }, "company_id": { "type": "integer" }, "category_id": { "type": "integer" }, } } }, "settings": { "index": { "analysis": { "analyzer": { "name_analyzer": { "type": "custom", "tokenizer": "standard", #        ,       "char_filter": [ "html_strip", #       html  "comma_to_dot_char_filter" #    ,     ], "filter": [ "word_delimeter_filter", #     "synonym_filter", #    "lowercase" #      ] } }, "filter": { "synonym_filter": { "type": "synonym_graph", "synonyms": [ ", ", ", ", ", ", ", , ", ", ", ", , , ", ", ", ", ", ", , ", ", , ", ", , , -, -", ", , ", ", , , ", ", ", ", ", ", , ", ", , ", ", ", ", ", ", ", ", ", ", , , ", ", ", ", g", "ml, " ] }, "word_delimeter_filter": { "type": "word_delimiter", "type_table": [ ". => DIGIT", #       "- => ALPHANUM", "; => SUBWORD_DELIM", "` => SUBWORD_DELIM" ] } }, "char_filter": { "comma_to_dot_char_filter": { "type": "mapping", "mappings": [ ", => ." ] } } } } } } 

Por exemplo, podemos observar em que partes o analisador "analisador de nomes" quebrará o nome da droga "Hioxisona 10mg + 30mg / g pomada para uso externo de um tubo de 10g". Usamos request _analyze .

 POST http://localhost:9200/app/_analyze { "analyzer" : "name_analyzer", "text" : " 10+30/      10" } 

resultado
 { "tokens": [ { "token": "", "start_offset": 0, "end_offset": 9, "type": "<ALPHANUM>", "position": 0 }, { "token": "10", "start_offset": 10, "end_offset": 12, "type": "<ALPHANUM>", "position": 1 }, { "token": "", "start_offset": 12, "end_offset": 14, "type": "<ALPHANUM>", "position": 2 }, { "token": "30", "start_offset": 15, "end_offset": 17, "type": "<ALPHANUM>", "position": 3 }, { "token": "", "start_offset": 17, "end_offset": 19, "type": "<ALPHANUM>", "position": 4 }, { "token": "g", "start_offset": 20, "end_offset": 21, "type": "SYNONYM", #,   "g"   SYNONYM,  ,          ", g" "position": 5 }, { "token": "", "start_offset": 20, "end_offset": 21, "type": "<ALPHANUM>", "position": 5 }, { "token": "", "start_offset": 22, "end_offset": 26, "type": "<ALPHANUM>", "position": 6 }, { "token": "", "start_offset": 27, "end_offset": 30, "type": "<ALPHANUM>", "position": 7 }, { "token": "", "start_offset": 31, "end_offset": 40, "type": "<ALPHANUM>", "position": 8 }, { "token": "", "start_offset": 41, "end_offset": 51, "type": "<ALPHANUM>", "position": 9 }, { "token": "", "start_offset": 52, "end_offset": 56, "type": "<ALPHANUM>", "position": 10 }, { "token": "10", "start_offset": 57, "end_offset": 59, "type": "<ALPHANUM>", "position": 11 }, { "token": "g", "start_offset": 59, "end_offset": 60, "type": "SYNONYM", "position": 12 }, { "token": "", "start_offset": 59, "end_offset": 60, "type": "<ALPHANUM>", "position": 12 } ] } 

Preenchendo Dados de Teste


Request _bulk

 POST http://localhost:9200/_bulk { "index": { "_index": "app", "_type": "product", "_id": 195111 } } { "name": " 10+30/      10", "manufacturer": "   ", "city_id": 1, "company_id": 2, "category_id": 1 } { "index": { "_index": "app", "_type": "product", "_id": 195222 } } { "name": "     10 +30 /: 10 ", "manufacturer": "", "city_id": 1, "company_id": 3, "category_id": 1 } 

Pesquisa de mapeamento


Deixe o produto do nosso cliente para o qual queremos encontrar todos os produtos similares dos concorrentes tenham características

 { "name": "     10 +30 /   10 ", "manufacturer": "   ", "city_id": 1, "company_id": 1, "category_id": 1 } 

Usando o diretório de medicamentos, selecionamos o nome do medicamento no nome do produto. Nesse caso, a palavra "Hyoxysone". Esta palavra será um critério obrigatório.

Também cortamos todos os números do nome - “10 30 10”, eles também serão um critério indispensável. Além disso, se um determinado número foi incluído duas vezes, ele também deve aparecer duas vezes nos produtos encontrados, caso contrário, aumentaremos a chance de coincidência com os produtos errados.

_ Solicitação de pesquisa

 GET http://localhost:9200/app/product/_search { "query": { "bool": { "filter": [ { "terms": { "company_id": [ 2, 3, 4, 5, 6, 7, 8 ] } }, { "term": { "city_id": { "value": 1, "boost": 1 } } }, { "term": { "category_id": { "value": 1, "boost": 1 } } } ], "must": [ { "bool": { "should": [ { "match": { "name": { "query": "    + /   ", "boost": 1, "operator": "or", "minimum_should_match": 0, "fuzziness": "AUTO" } } } ], "must": [ { "match": { "name": { "query": "", "boost": 2, "operator": "or", "minimum_should_match": "70%", "fuzziness": "AUTO" } } }, { "match_phrase": { "name": { "query": "10 30 10", "boost": 2, "slop": 100 } } } ] } } ], "should": [ { "bool": { "should": [ { "match": { "manufacturer": { "query": "   ", "boost": 1, "operator": "or", "minimum_should_match": "70%", "fuzziness": "AUTO" } } }, { "match": { "manufacturer": { "query": "alenta armacevtika ", "boost": 1, "operator": "or", "minimum_should_match": "70%", "fuzziness": "AUTO" } } } ] } } ] } }, "highlight": { "fields": { "name": {} } }, "size": 50 } 

Na saída, obtemos o ID das mercadorias, bem como seu nome + pontuação para análises, com fragmentos correspondentes correspondentes.

  • Hyoxysone 10 mg + 30 mg / g pomada para uso externo , tubo 10 g - Pontuação no algoritmo: 69.84
  • HYOXISON pomada para uso externo 10 mg + 30 mg / g : 10 g - Avaliação de algoritmo: 49.79

Conclusão


O método descrito certamente não fornecerá 100% de precisão na correspondência, mas facilitará bastante o processo de correspondência manual de mercadorias. Também adequado para tarefas que não exigem precisão absoluta.
Em geral, se você melhorar sua consulta de pesquisa usando heurísticas adicionais e aumentar o número de sinônimos, poderá obter um resultado quase satisfatório.
Além disso, os testes de desempenho realizados no antigo i7 mostraram bons resultados. 10 consultas de pesquisa em uma matriz de 200.000 produtos são realizadas em alguns segundos. Você pode ver este exemplo ao vivo da medicina aqui .

Sugira suas opções, formas de correspondência nos comentários.

Obrigado pela atenção!

Source: https://habr.com/ru/post/pt428814/


All Articles