Эквивалент MySql Order By Value в ElasticSearch 5.6

Версия ElasticSearch: 5.6

Я импортировал данные MySQL в ElasticSearch и при необходимости добавил сопоставление с эластичным поиском. Ниже приведено одно сопоставление для столбца application_status.

Сопоставления:

{
"settings": {
    "analysis": {
        "analyzer": {
            "case_insensitive": {
                "type": "custom",
                "tokenizer": "keyword",
                "filter": ["lowercase"]
            }
        }
    }
},
"mappings": {
    "lead": {
        "properties": {
            "application_status": {
                "type": "string",
                "analyzer": "case_insensitive",
                "fields": {
                    "keyword": {
                        "type": "keyword"
                    }
                }
            }
        }
    }
}}

На приведенном выше сопоставлении я могу выполнить простую сортировку (asc или desc), используя следующий запрос:

{
"size": 50,
"from": 0,
"sort": [{
    "application_status.keyword": {
        "order": "asc"
    }
}]}

который является MySql эквивалентом

select * from <table_name> order by application_status asc limit 50;

Нужна помощь по следующей проблеме: У меня есть запрос MySQL, который сортируется на основе application_status:

select * from vLoan_application_grid order by CASE WHEN application_status = "IP_QUAL_REASSI" THEN application_status END desc, CASE WHEN application_status = "IP_COMPLE" THEN application_status END desc, CASE WHEN application_status LIKE "IP_FRESH%" THEN application_status END desc, CASE WHEN application_status LIKE "IP_%" THEN application_status END desc

Помогите, пожалуйста, написать такой же запрос в ElasticSearch. Я не могу найти эквивалент order by value для strings в ElasticSearch. Поискав в Интернете, я понял, что мне следует использовать sorting scripts, но не смог найти подходящей документации.

У меня есть следующий запрос, который просто выполняет простую сортировку.

{
"size": 500,
"from": 0,
"query" : {
    "match_all": {}
},
"sort": {
    "_script": {
        "type": "string",
        "script": {
            "source": "doc['application_status.keyword'].value",
            "params": {
                "factor": ["IP_QUAL_REASS", "IP_COMPLE"]
            }
        },
        "order": "desc"
    }
}}

В приведенном выше запросе я не использую раздел params, так как не знаю, как его использовать для type: string.

Я считаю, что прошу слишком много. Пожалуйста, помогите или любые соответствующие ссылки на документацию будут очень признательны. Надеюсь, вопрос ясен. При необходимости предоставлю более подробную информацию.


person Sagar Chilukuri    schedule 02.11.2017    source источник
comment
Я не эксперт в MySQL, но, возможно, я могу помочь с Elasticsearch. Можете ли вы объяснить, что делает этот оператор сортировки, который у вас есть в MySQL?   -  person Andrei Stefan    schedule 02.11.2017
comment
Столбец application_status может иметь несколько значений. Мне нужно отсортировать приложение по его значению статуса. Предположим, что у 10 приложений есть application_status = 'IP_QUAL_REASS', а у 5 – application_status = 'IP_COMPLE', тогда приложения со статусом IP_QUAL_REASS должны оказаться наверху, а приложения со вторым условием - ниже.   -  person Sagar Chilukuri    schedule 02.11.2017
comment
Проще говоря, помогите мне отсортировать столбец на основе значений столбца.   -  person Sagar Chilukuri    schedule 02.11.2017
comment
"sort": [{ "application_status.keyword": { "order": "asc" } }]} делает именно это.   -  person Andrei Stefan    schedule 02.11.2017
comment
Нет, сэр. Его сортировка всего столбца независимо от значений. В MySQL это разница между sort и sort by value. sort by value значение сначала упорядочивает строки по значениям их полей. Пожалуйста, проверьте electrictoolbox.com/mysql-order-specific-field-values.   -  person Sagar Chilukuri    schedule 02.11.2017


Ответы (1)


У вас есть два варианта:

  • наиболее эффективным является индексирование во время индексации другого поля, которое должно быть числом. Это число (по вашему выбору) будет числовым представлением этого статуса. Затем во время поиска вы просто сортируете по этому номеру, а не по статусу
  • во время поиска используйте скрипт, который будет делать почти то же самое, что и первый вариант, но динамически и менее производительно (но все же достаточно быстро)

Ниже у вас есть второй вариант:

  "sort": {
    "_script": {
      "type": "number",
      "script": {
        "source": "if (params.factor[0].containsKey(doc['application_status.keyword'].value)) return params.factor[0].get(doc['application_status.keyword'].value); else return 1000;",
        "params": {
          "factor": [{
            "IP_QUAL_REASS":1,
            "IP_COMPLE":2,
            "whatever":3
          }
          ]
        }
      },
      "order": "asc"
    }
  }

Если вам также нужны такие вещи, как LIKE WHATEVER%, я предлагаю подумать об изменении времени индексации, а не времени поиска, потому что сценарий становится более сложным. Но это также и для совпадений с подстановочными знаками:

  "sort": {
    "_script": {
      "type": "number",
      "script": {
        "source": "if (params.factor[0].containsKey(doc['application_status.keyword'].value)) return params.factor[0].get(doc['application_status.keyword'].value); else { params.wildcard_factors[0].entrySet().stream().filter(kv -> doc['application_status.keyword'].value.startsWith(kv.getKey())).map(Map.Entry::getValue).findFirst().orElse(1000)}",
        "params": {
          "factor": [
            {
              "IP_QUAL_REASS": 1,
              "IP_COMPLE": 2,
              "whatever": 3
            }
          ],
          "wildcard_factors": [
            {
              "REJ_": 66
            }
          ]
        }
      },
      "order": "asc"
    }
  }
person Andrei Stefan    schedule 02.11.2017
comment
Ух ты. Он отлично обрабатывает точное совпадение строк. Как мне обрабатывать строки с подстановочными знаками, как указано в вопросе 3. Например: application_status LIKE "REJ_%" THEN application_status END desc. В нем описывается, что если какое-либо application_status начинается с REJ%, то упорядочить значение. - person Sagar Chilukuri; 02.11.2017
comment
Есть ли так много значений для этого статуса, что вы не можете просто перечислить их в параметре скрипта? - person Andrei Stefan; 02.11.2017
comment
Возможны 74 состояния. Я могу перечислить их в параметрах скрипта, но тогда это будет означать жесткое кодирование статусов. В будущем, если будет добавлен какой-либо новый статус, мне также придется обновить эластичный поиск. Просто хочу реализовать динамически; если возможно - person Sagar Chilukuri; 02.11.2017
comment
Я также добавил скрипт для совпадений с подстановочными знаками. - person Andrei Stefan; 02.11.2017