Запрос непроданных продуктов от ElasticSearch - PullRequest
2 голосов
/ 18 октября 2019

Я новичок вasticSearch и мне нужна помощь ...

У меня есть индекс продаж с такими записями:

{product.id : 12 , sales.datetime : October 12th 2019},
{product.id : 13 , sales.datetime : October 12th 2019},
{product.id : 14 , sales.datetime : October 13th 2019},
{product.id : 14 , sales.datetime : October 14th 2019},
{product.id : 14 , sales.datetime : October 14th 2019},
{product.id : 13 , sales.datetime : October 18th 2019},
                             ...

Я хотел бы получить продуктынепроданный 12 октября 2019 года,

Я пытался отфильтровать данные по sales.datetime с помощью:

"range" => [
             "datetime" => [
                    "lt" => "October 12th 2019"
                ]
            ] 

Но очевидно, что этот тип запроса будет возвращать неожиданные значения, например, в этом случае, он получит product.id : [12,13], но вы можете видеть, что product.id был продан 18 октября 2019 года ...

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Отображения:

PUT sales
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "date":{
        "type": "date",
        "format": "MM-dd-yyyy" 
      }
    }
  }
}

Данные:

 [
      {
        "_index" : "sales",
        "_type" : "_doc",
        "_id" : "I-6Y7W0B_-hMjUaqpQH4",
        "_score" : 1.0,
        "_source" : {
          "id" : 12,
          "date" : "10-12-2019"
        }
      },
      {
        "_index" : "sales",
        "_type" : "_doc",
        "_id" : "JO6Y7W0B_-hMjUaqtwEL",
        "_score" : 1.0,
        "_source" : {
          "id" : 13,
          "date" : "10-12-2019"
        }
      },
      {
        "_index" : "sales",
        "_type" : "_doc",
        "_id" : "Je6Y7W0B_-hMjUaqxgEH",
        "_score" : 1.0,
        "_source" : {
          "id" : 13,
          "date" : "10-18-2019"
        }
      }
    ]

Запрос: - получить максимальную дату для всех терминов, получить максимальную дату, где диапазон дат меньше 2019-10-12, если обаэто то же самое возвращаемое ведро

GET sales/_search
{
  "size": 0,
  "aggs": {
    "transactionId": {
      "terms": {
        "field": "id",
        "size": 10000
      },
      "aggs": {
        "maxDate": {
          "max": {
            "field": "date"
          }
        },
        "pending_status": {
          "filter": {
            "range": {
              "date": {
                "lte": "10-12-2019"
              }
            }
          },
          "aggs": {
            "filtered_maxdate": {
              "max": {
                "field": "date"   
              }
            }
          }
        },
        "buckets_latest_status_pending": {
          "bucket_selector": {
            "buckets_path": {
              "filtereddate": "pending_status>filtered_maxdate",
              "maxDate": "maxDate"
            },
            "script": "params.filtereddate==params.maxDate"
          }
        }
      }
    }
  }
}

Ответ:

 [
        {
          "key" : "12",
          "doc_count" : 1,
          "pending_status" : {
            "doc_count" : 1,
            "filtered_maxdate" : {
              "value" : 1.5708384E12,
              "value_as_string" : "10-12-2019"
            }
          },
          "maxDate" : {
            "value" : 1.5708384E12,
            "value_as_string" : "10-12-2019"
          }
        }
      ]

РЕДАКТИРОВАТЬ 1:

Вы можете использовать (top_hits) [https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-top-hits-aggregation.html] агрегирование, чтобы получить вседокументы в корзине

GET sales/_search
{
  "size": 0,
  "aggs": {
    "transactionId": {
      "terms": {
        "field": "id",
        "size": 10000
      },
      "aggs": {
        "maxDate": {
          "max": {
            "field": "date"
          }
        },
        "pending_status": {
          "filter": {
            "range": {
              "date": {
                "lte": "10-12-2019"
              }
            }
          },
          "aggs": {
            "filtered_maxdate": {
              "max": {
                "field": "date"   
              }
            }
          }
        },
        "buckets_latest_status_pending": {
          "bucket_selector": {
            "buckets_path": {
              "filtereddate": "pending_status>filtered_maxdate",
              "maxDate": "maxDate"
            },
            "script": "params.filtereddate==params.maxDate"
          }
        },
        "top_hits":{   ---> top hits to get all documents under a bucket
          "top_hits": {
            "size": 10
          }
        }
      }
    }
  }
}

Для разбивки на страницы можно использовать составное агрегирование / , включая разделы

1 голос
/ 18 октября 2019

Давайте сделаем шаг назад и поймем, что мы пытаемся сделать.

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

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

Отображение:

PUT sales
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "date":{
        "type": "date",
        "format": "MM-dd-yyyy" 
      }
    }
  }
}

Образцы документов:

POST sales/_doc/1
{ 
  "id" : 12 , 
  "date" : ["10-12-2019", "10-18-2019"]       <--- Note this
}

POST sales/_doc/2
{ 
  "id" : 13 , 
  "date" : ["10-12-2019"]
}

POST sales/_doc/3
{ 
  "id" : 14 , 
  "date" : ["10-10-2019", "10-14-2019"]
}

Запрос:

POST sales/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "date": {
              "lte": "10-12-2019"
            }
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "date": {
              "gt": "10-12-2019"
            }
          }
        }
      ]
    }
  }
}

Обратите внимание, как запрос был построен в оченьупрощенный способ использования пунктов must и must_not.

Ответ:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "sales",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "id" : 13,
          "date" : [
            "10-12-2019"
          ]
        }
      }
    ]
  }
}

Обратите внимание, что в ответе вы получаете только искомый документ.

Надеюсь, это поможет!

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