Elasticsearch расширенная сортировка с оператором if - PullRequest
0 голосов
/ 17 января 2019

В моем ES есть объекты "персона", которые могут выглядеть так:

{
 name: "a",
 type: "single"
}


{
 name: "b",
 type: "family",
 children: {
   {
     name: "ba",
     active: 1
   },
   {
     name: "bb",
     active: 0
   }
 }
}

{
 name: "c",
 type: "family",
 children: {
   {
     name: "ba",
     active: 0
   },
   {
     name: "bb",
     active: 0
   }
 }
}

Теперь я хотел бы получить все "персона", но ... if type = family and all children active = 0 тогда этот объект должен быть в нижней части списка (_score = 0)

Как я могу получить этот тип сортировки?

1 Ответ

0 голосов
/ 17 января 2019

Вы можете сделать это несколькими разными способами с похожими результатами:

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

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

Отображение условного поля

{
  "mappings": {
    "_doc" : {
      "properties" : {
        "name": {
          "type": "text"
        },
        "type": {
          "type": "keyword"
        },
        "children" : {
          "type" : "nested",
          "properties": {
            "name": {
              "type": "text",
            },
            "active": {
              // Unless you intend to do some math with the active
              // field, you should probably us a boolean for this flag
              "type": "boolean"
            }
          }
        }
      }
    }
  }
}

Условный запрос

{
  "query": {
    "function_score": {
      "query": { "match_all": {}},
      // Other options available for boost_mode, e.g. multiply--see docs
      "boost_mode": "sum",
      "functions": [
        {
          // You'll need to tweak this weighting, depending on your query
          "weight": 5,
          "filter": {
            "bool": {
              "must": [
                // Filters this boost to apply only to `type: family`
                { "term" : { "type" : "family" }}, 
                // Nested query to select items with active children.  
                // Using `score_mode: sum` means that more active children will
                // give more of a boost.  Other score modes available
                {
                  "nested": {  
                    "path" : "children",
                    "score_mode" : "sum",
                    "query" : {
                      "bool" : {
                        "must" : [
                          { "term" : { "children.active" : true }}
                        ]
                      }
                    }
                  }
                } 
              ]
            }
          }
        }
      ]
    }
  }
}

Это применит усиление к записям, у которых есть активные дочерние элементы, а остальные останутся внизу. В качестве альтернативы вы можете написать запрос, который соответствует только записям, у которых нет активных дочерних элементов, и применить отрицательный вес.

Если у вас есть еще один вопрос о том, как заставить работать любую из этих частей, просто задайте другой вопрос, относящийся к вашей проблеме. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...