Full Text Search + сортировка + фильтры + nested в одном запросе


#1

Здравствуйте!
Только начал изучать ES, составил запрос, он работает.

  1. Но нужна оценка профессионала,
    относительно производительности этого запроса при выборке из большой базы.

  2. Если есть возможность, пожалуйста, дайте совет как правильно делать запросы такого типа (порядок запросов).

  3. Есть ли у ES встроенные инструменты для определения скорости ответа?

     GET index/type/_search
     {
     "sort":[{
         "price":{
             "order" : "desc"
         }
     }],
     "query": {
         "filtered":{
             "filter": {
                   "bool": {
                     "should": [
                       { "term": { "type_prod": 1 }}
                     ],
                     "minimum_should_match":"100%"
                   }
                 },
           "query": {
               "query_string":{
                   "fields" : ["title","body"],
                   "query":"брюки мужские",
                   "default_operator" : "or",
                   "analyzer":"autocomplete",
                   "allow_leading_wildcard":"*",
                   "enable_position_increments":true,
                   "fuzzy_max_expansions":3,
                   "fuzziness":2,
                   "fuzzy_prefix_length":1,
                   "phrase_slop":"1",
                   "boost":"1.0",
                   "analyze_wildcard":true,
                   "auto_generate_phrase_queries":"true",
                   "max_determinized_states":10000,
                   "minimum_should_match":"30%"
               }
           }
         }
     },
     "query": {
         "nested": {
                 "path": "attribute",
                 "query": {
                       "bool": {
                           "must": [
                               { "match": { "attribute.size": "48" }}
                           ]
                       }
                 }
           }
     }
     }

(Igor Motov) #2

Сложно что-то сказать глядя только на запрос, кроме того, что он не правильный поскольку у него два параметра "query" на верхнем уровне. Хотелось бы узнать больше деталей о меппинге и типах запросов, которые вы собираетесь выполнять. Например, из этого запроса совсем не понятно зачем size помещен в nested. Я могу только предполагать, что вы также собираетесь искать по определенному размеру и цвету и не для каждого размера цвет имеется в наличии, или что-то в этом роде. В противном случае использование nested не имеет смысла. От анализатора тоже много что зависит, но в вашем примере его нет.

Для анализа запросов, можно воспользоваться search profiler, но сначала надо разобраться с самим запросом и его починить.


#3

Спасибо за оперативный ответ.

// SETTINGS & MAPPINGS

"settings":{
  "number_of_shards":1,
  "number_of_replicas":0,
  "analysis":{
    "filter":{
      "autocomplete_filter" : {
        "type":"edge_ngram",
        "min_gram": 1,
        "max_gram": 15
      },
      "my_stopwords": {
          "type": "stop",
          "stopwords": "а,без,более,бы"
        },
       "my_synonyms": {
         "type": "synonym",
         "synonyms" : [ "штаны, шировары => брюки","брюки, штаны => шировары" ]
        }
    },
    "analyzer":{
      "autocomplete":{
        "type":"custom",
        "tokenizer":"standard",
        "filter":["lowercase", "autocomplete_filter"]
      },
      "my_search_analyzer": {
           "type": "custom",
           "tokenizer": "standard",
           "filter": [ "lowercase", "russian_morphology", "english_morphology", "my_stopwords", "my_synonyms" ]
       }
    }
  }
},
"mappings":{
  "_default_":{
    "_source":{
      "enabled": true
    },
    "properties":{
      "date_upd":{
        "type":"date",
        "doc_values":true,
        "index":"not_analyzed"
      },
      "title":{
        "type":"string",
        "analyzer": "autocomplete",
        "search_analyzer": "my_search_analyzer"
      },
      "body":{
        "type":"string",
        "analyzer": "my_search_analyzer",
        "search_analyzer": "my_search_analyzer"
      },
      "attribute":{
        "type":"nested",
        "properties":{
          "size":{
            "type":"string",
            "analyzer": "my_search_analyzer",
            "search_analyzer": "my_search_analyzer"
          }
        }
      },
      "type_prod":{
        "type":"string",
        "doc_values":true,
        "index":"not_analyzed"
      },
      "price":{
        "type":"string",
        "doc_values":true,
        "index":"not_analyzed",
        "null_value": "NULL"
      }
    }
  }
}

// BODY
{
"date_upd" : "2016-01-01",
"title" : "Продам брюки мужские",
"body" : "Материал хлопок, производство Россия",
"attribute":{
"size":[ "m", "l", "48" ]
},
"type_prod" : 1,
"price" : 900
}

Отдельным query поставил исходя из мануала, пробовал сделать все это в одном запросе, получал ошибки.
Вы правы, в attribute планируются данные о товаре такие как размер, цвет, в некоторых товарах там может быть к примеру длина рукава, в других массив данных максимум [x1, x2, x3], минимум [x1] - товары планируются разные, соответственно и атрибуты, но думаю формат этих данных можно будет уложить в массив [x1, x2, x3,........]. В мануале читал, что nested по умолчанию динамический тип данных,

1. Можно ли в nested добавлять новые поля по ходу развития проекта с возможность поиска в этом массиве ( [x1, x2, x3]) - x1 и / или x2, x3?

2. Можно ли применить какой то другой, более удачный динамический тип данных для хранения массива вида [x1, x2, x3], с возможностью поиска в нем x1 и/или x2, x3?

3. Сейчас запрос выстроен в таком порядке:
а.) сортируется в обратном порядке
б.) выбирается только тип продукции №1
в.) осуществляется ПП
Вопрос: при осуществлении полнотекстового поиска ES учитывает только типы №1? т.е. операция произведенная в пункте "б." уже отсеяла все други типы и ПП стало проще осуществить или порядок запросов не имеет значения?


(Igor Motov) #4

То есть когда пользователь ищет шировары, вы вместо этого ищите брюки и наоборот? Не очень, понятно что вы пытаетесь добиться этим. Я думаю можно было бы оставить только "штаны, шировары => брюки", если это не работает, то причина, скорее всего, в каком-то другом место (см ниже)

Использование autocomplete для индексирования и my_search_analyzer для поиска, может также привезти к проблемам, так как при поиске вы приводите слова к их корням, а при индексировании этого не происходит.

Я все еще не вижу особого смысла в использовании nested, так как вы все-равно все сваливаете в один массив вместо использования массива nested объектов. Так что связь между атрибутами не сохраняется. Я бы понял, если бы было как-то так:

"attribute": [{
    "size": "m",
    "color": ["red", "blue"]
}, {
    "size": "l",
    "color": ["green", "blue", "yellow"]
}, {
    "size": "48",
    "color": ["black"]
}],

и вы ищете size:48 и color:green в одном запросе.

Вы знакомы с Elasticsearch: The Definitive Guide? Я, думаю, что было бы полезно начать и изучения этой книги, поскольку все эти вопросы там хорошо описаны.


#5

Спасибо, будем изучать.


(system) #6