ElasticSearch: Как создать конвейер агрегации? - PullRequest
1 голос
/ 08 апреля 2020

Представьте себе следующий вариант использования:

Мы работаем в Stark Airlines, и наша маркетинговая команда хочет сегментировать наших пассажиров, чтобы предоставить им скидки или подарочные карты. Они решают, что им нужны две группы пассажиров:

  1. Пассажиры, которые летают не менее 3 раз в неделю
  2. Пассажиры, которые летали хотя бы один раз, но которые не летали в течение двух недель

При этом они могут проводить различные маркетинговые кампании для наших пассажиров!

Итак, в поиске elasti c у нас есть индекс trip, который представляет билет, купленный пассажиром:

{
   "_index" : "trip",
   "_type" : "_doc",
   "_id" : "1",
   "_score" : 1.0,
   "_source" : {
       "total_amount" : 300,
       "trip_date" : "2020/03/24 13:30:00",
       "status" : "completed",
       "passenger" : {
          "id" : 11,
          "name" : "Thiago nunes"
       }
     }
}

Индекс trip содержит поле status, которое может иметь другие значения, такие как: pending или open или canceled

Это означает, что мы можем только принять во внимание поездки, которые имеют статус completed (имеется в виду, что пассажир действительно путешествовал).

Итак, учитывая все это ... Как бы я получил эти две группы пассажиров с помощью поиска elasti c ?

Я пытался некоторое время, но безуспешно.

Что я делал до сих пор:

  1. Я построил запрос, который получает все действительные поездки (поездки со статусом completed)
GET /trip/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "status": {
              "value": "completed"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "status_viagem": {
      "terms": {
        "field": "status.keyword"
      }
    }
  }
}
Этот запрос возвращает следующее:
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 200,
      "relation" : "eq"
    },
    "max_score" : 0.18232156,
    "hits" : [...]
  },
  "aggregations" : {
    "status_viagem" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "completed",
          "doc_count" : 200
        }
      ]
    }
  }
}

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

Может ли кто-нибудь помочь?

PS .:

  1. Мне точно не нужно, чтобы это было одно запрос, просто подсказка о том, как создать такой запрос, было бы очень полезно

  2. Выход должен быть массивом идентификатора пассажира

  3. Примечание: для простоты я сократил индекс trip

1 Ответ

0 голосов
/ 09 апреля 2020

В соответствии с моим пониманием вашей проблемы.

Я использовал date_histogram с интервалом в качестве недели, чтобы получить данные о пассажирах за эту неделю. Сохраняются только те пассажиры, у которых есть три документа в неделю. Это даст вам всех пассажиров, которые путешествовали трижды за неделю.

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

Отображение

{
  "index87" : {
    "mappings" : {
      "properties" : {
        "passengerid" : {
          "type" : "long"
        },
        "passengername" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "status" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "total_amount" : {
          "type" : "long"
        },
        "trip_date" : {
          "type" : "date"
        }
      }
    }
  }
}

Запрос

{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "status": {
              "value": "completed"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "travel_thrice_week": {
      "date_histogram": {
        "field": "trip_date",
        "interval": "week"
      },
      "aggs": {
        "passenger": {
          "terms": {
            "field": "passengername.keyword",
            "min_doc_count": 3,
            "size": 10
          }
        },
        "select_bucket_with_user": {-->to keep weeks which have a pasenger with thrice 
                                    --> a day travel
          "bucket_selector": {
            "buckets_path": {
              "passenger": "passenger._bucket_count"
            },
            "script": "if(params['passenger']>=1) {return true;} else{ return false;} "
          }
        }
      }
    },
    "not_flown_last_two_week": {
      "terms": {
        "field": "passengername.keyword",
        "size": 10
      },
      "aggs": {
        "last_travel": {
          "max": {
            "field": "trip_date" -->  most recent travel
          }
        },
        "last_travel_before_two_week": {
          "bucket_selector": {
            "buckets_path": {
              "traveldate": "last_travel"
            },
            "script":{
              "source": "if(params['traveldate']< params['date_epoch']) return true; else return false;",
              "params": {
                "date_epoch":1586408336000 --> unix epoc of cutt off date
              }
            }

          }
        }
      }
    }
  }
}

Результат:

"aggregations" : {
    "not_flown_last_two_week" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Thiago nunes",
          "doc_count" : 3,
          "last_travel" : {
            "value" : 1.5851808E12,
            "value_as_string" : "2020-03-26T00:00:00.000Z"
          }
        },
        {
          "key" : "john doe",
          "doc_count" : 1,
          "last_travel" : {
            "value" : 1.5799968E12,
            "value_as_string" : "2020-01-26T00:00:00.000Z"
          }
        }
      ]
    },
    "travel_thrice_week" : {
      "buckets" : [
        {
          "key_as_string" : "2020-03-23T00:00:00.000Z",
          "key" : 1584921600000,
          "doc_count" : 3,
          "passenger" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Thiago nunes",
                "doc_count" : 3
              }
            ]
          }
        }
      ]
    }
  }
...