Elasticsearch Конвейерный поиск? - PullRequest
0 голосов
/ 09 октября 2019

Я уже некоторое время использую Elasticsearch в своей компании и, похоже, до сих пор работал хорошо для наших поисков. Мы наблюдаем более сложные варианты использования от наших клиентов, которым требуются дополнительные «специальные / расширенные» возможности запросов и связи между документами (или объединения в традиционном смысле). Я понимаю, что ES не создан для соединений и денормализация является рекомендуемым способом. Мы до сих пор денормализуем документы для поддержки каждого варианта использования, и это само по себе стало слишком сложным и дорогостоящим делом для нас, поскольку нашим клиентам приходится долго ждать, чтобы это изменение кода было развернуто.

Наш бизнес все чаще критиковал нас за то, что «Эй, ваша модель данных неверна. Она не подходит для более интеллектуальных запросов». Команде каждый раз мучительно труднее заставить их понять, почему требуется денормализация.

Несколько примеров проблем:

"Find me all the persons having the same birthdays"
"Find me all the persons travelling to the same cities within the same time frame"

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

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

1 Ответ

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

Два вышеуказанных запроса могут быть решены с помощью агрегатов.

Я предполагаю следующий образец документа / схемы:

{
  "firstName": "John",
  "lastName": "Doe",
  "birthDate": "1998-04-02",
  "travelDate": "2019-10-31",
  "city": "London"
}

Первый, который агрегируется с terms в поле даты рождения (деньгод) и min_doc_count: 2, например:

{
  "size": 0,
  "aggs": {
    "birthdays": {
      "terms": {
        "script": "return LocalDate.parse(params._source.birthDate).format(DateTimeFormatter.ofPattern('MM/dd'))",
        "min_doc_count": 2
      },
      "aggs": {
        "persons": {
          "top_hits": {}
        }
      }
    }
  }
}

Второй - агрегирование с агрегацией terms в поле city и ограничение с помощью запроса range в поле travelDate дляжелаемый период времени:

{
  "size": 0,
  "query": {
    "range": {
      "travelDate": {
        "gte": "2019-10-01",
        "lt": "2019-11-01"
      }
    }
  },
  "aggs": {
    "cities": {
      "terms": {
        "field": "city.keyword"
      },
      "aggs": {
        "persons": {
          "top_hits": {}
        }
      }
    }
  }
}

Второй запрос также можно выполнить с помощью свертывания полей :

{
  "_source": false,
  "query": {
    "range": {
      "travelDate": {
        "gte": "2019-10-01",
        "lt": "2019-11-01"
      }
    }
  },
  "collapse": {
    "field": "city.keyword",
    "inner_hits": {
      "name": "people"
    }
  }
}

Если вам нужны обе агрегации одновременно,это определенно возможно сделать так:

{
  "size": 0,
  "aggs": {
    "birthdays": {
      "terms": {
        "script": "return LocalDate.parse(params._source.birthDate).format(DateTimeFormatter.ofPattern('MM/dd'))",
        "min_doc_count": 2
      },
      "aggs": {
        "persons": {
          "top_hits": {}
        }
      }
    },
    "travels": {
      "filter": {
        "range": {
          "travelDate": {
            "gte": "2019-10-01",
            "lt": "2019-11-01"
          }
        }
      },
      "aggs": {
        "cities": {
          "terms": {
            "field": "city.keyword"
          },
          "aggs": {
            "persons": {
              "top_hits": {}
            }
          }
        }
      }
    }
  }
}
...