ElasticSearch 다단계 부모-자식 집계
나는 3 단계의 부모 / 자식 구조를 가지고 있습니다. 의 말을하자:
회사-> 직원-> 가용성
가용성 (및 직원)이 여기에서 자주 업데이트되므로 중첩에 대해 상위 / 하위 구조를 사용하도록 선택합니다. 그리고 검색 기능이 제대로 작동합니다 (올바른 샤드의 모든 문서).
이제 그 결과를 정렬하고 싶습니다. 회사 (1 단계)의 메타 데이터로 정렬하는 것은 쉽습니다. 하지만 3 단계 (가용성)로도 정렬해야합니다.
다음으로 정렬 된 회사 목록을 원합니다.
- ASC가 주어진 위치로부터의 거리
- 평가 DESC
- 빠른 가용성 ASC
예를 들면 :
회사 A는 5 마일 떨어져 있고 등급 4이며 가장 빠른 직원 중 한 명이 20 시간 내에 이용 가능합니다. 회사 B도 5 마일 떨어져 있으며 등급 4도 있지만 가장 빨리 직원 중 한 명은 5 시간 내에 이용 가능합니다.
따라서 정렬 결과는 B, A 여야합니다.
이 데이터 각각에 특별한 가중치를 추가하고 싶기 때문에 나중에 custom_score 스크립트에서 사용할 수있는 집계 작성을 시작했습니다.
인덱스 생성, 데이터 가져 오기 및 검색에 대한 전체 요점
이제 실제로 결과를 반환하는 쿼리를 작성했지만 가용성 집계 버킷이 비어 있습니다. 그러나 결과가 너무 구조화되어 있으므로 평평하게 만들고 싶습니다.
현재 돌아온다 :
회사 ID-> 직원 ID-> 첫 번째 가용성
다음과 같은 집계를 원합니다.
회사 IDS-> 첫 번째 가용성
이렇게하면 custom_score
점수를 계산하고 올바르게 정렬하는 스크립트를 수행 할 수 있습니다.
더 간단한 질문 :
어떻게 다단계 (손자)를 기준으로 정렬 / 집계하고 결과를 평평하게 만들 수 있습니까?
이를 위해 집계가 필요하지 않습니다.
다음은 정렬 기준입니다.
- 거리 ASC (회사. 위치)
- 등급 DESC (company.rating_value)
- 곧 미래 가용성 ASC (company.employee.availability.start)
# 3을 무시하면 다음 과 같이 비교적 간단한 회사 쿼리를 실행할 수 있습니다 .
GET /companies/company/_search
{
"query": { "match_all" : {} },
"sort": {
"_script": {
"params": {
"lat": 51.5186,
"lon": -0.1347
},
"lang": "groovy",
"type": "number",
"order": "asc",
"script": "doc['location'].distanceInMiles(lat,lon)"
},
"rating_value": { "order": "desc" }
}
}
# 3 은 요청 시점에 가장 가까운 각 회사 의 가용성 ( 회사> 직원> 가용성 )을 찾아야하고 해당 기간을 세 번째 정렬 기준 으로 사용해야 하기 때문에 까다 롭습니다 .
function_score
요청 시간과 히트의 각 가용성 사이의 시간 차이를 가져 오기 위해 손자 수준에서 쿼리 를 사용할 것 _score
입니다. (그런 다음 _score
세 번째 정렬 기준으로를 사용합니다 .)
손자에게 도달하려면 has_child
쿼리 내에서 has_child
쿼리 를 사용해야 합니다.
각 회사에 대해 우리는 가능한 가장 빠른 직원 (물론 가장 가까운 가용성)을 원합니다. Elasticsearch 2.0은 "score_mode": "min"
이와 같은 경우 에 대해 우리에게 제공 할 것이지만, 지금 "score_mode": "max"
은 손자를 시간차 _score
의 역수 로 만드는 것으로 제한되어 있습니다 .
"function_score": {
"filter": {
"range": {
"start": {
"gt": "2014-12-22T10:34:18+01:00"
}
}
},
"functions": [
{
"script_score": {
"lang": "groovy",
"params": {
"requested": "2014-12-22T10:34:18+01:00",
"millisPerHour": 3600000
},
"script": "1 / ((doc['availability.start'].value - new DateTime(requested).getMillis()) / millisPerHour)"
}
}
]
}
그래서 지금은 _score
각각의 손자 (대한 가용성 )입니다 1 / number-of-hours-until-available
(그래서 우리가 사용할 수있는 최대 상호 직원 당 가능하고, 때까지 시간을 최대 상호 (LY?) 회사 당 가능 직원).
Putting it all together, we continue to query company but use company > employee > availabilty to generate the _score
to use as the #3 sort criterion:
GET /companies/company/_search
{
"query": {
"has_child" : {
"type" : "employee",
"score_mode" : "max",
"query": {
"has_child" : {
"type" : "availability",
"score_mode" : "max",
"query": {
"function_score": {
"filter": {
"range": {
"start": {
"gt": "2014-12-22T10:34:18+01:00"
}
}
},
"functions": [
{
"script_score": {
"lang": "groovy",
"params": {
"requested": "2014-12-22T10:34:18+01:00",
"millisPerHour": 3600000
},
"script": "1/((doc['availability.start'].value - new DateTime(requested).getMillis()) / millisPerHour)"
}
}
]
}
}
}
}
}
},
"sort": {
"_script": {
"params": {
"lat": 51.5186,
"lon": -0.1347
},
"lang": "groovy",
"type": "number",
"order": "asc",
"script": "doc['location'].distanceInMiles(lat,lon)"
},
"rating_value": { "order": "desc" },
"_score": { "order": "asc" }
}
}
You should check out R-Tree data structure https://en.wikipedia.org/wiki/R-tree.
참고URL : https://stackoverflow.com/questions/27510798/elasticsearch-multi-level-parent-child-aggregation
'Development Tip' 카테고리의 다른 글
Safari 페이지가 iOS 렌더링을 중단하는 이유는 무엇입니까? (0) | 2020.10.10 |
---|---|
원시 스토리지를 사용할 때 EBO를 에뮬레이트하는 방법은 무엇입니까? (0) | 2020.10.10 |
블루투스 핸즈프리 클라이언트 볼륨 제어 (0) | 2020.10.10 |
Docker 및 --userns-remap, 호스트와 컨테이너간에 데이터를 공유하기 위해 볼륨 권한을 관리하는 방법은 무엇입니까? (0) | 2020.10.10 |
Java 문자열에서 인쇄 할 수없는 모든 문자를 제거하는 가장 빠른 방법 (0) | 2020.10.10 |