3 レベルの親/子構造があるとします。次のようにします。
会社 -> 従業員 -> 空き状況
ここでは可用性 (および従業員) が頻繁に更新されるため、ネストではなく親/子構造を使用することを選択します。また、検索機能は正常に動作します (すべてのドキュメントが正しいシャード内にあります)。
次に、これらの結果を並べ替えます。会社 (第 1 レベル) のメタデータで並べ替えるのは簡単です。ただし、第 3 レベル (可用性) でも並べ替える必要があります。
以下の基準で並べ替えられた企業のリストが欲しい:
- ASC で指定された場所からの距離
- 評価DESC
- 最も早く利用可能 ASC
例えば:
会社 A は 5 マイル離れており、評価は 4 で、従業員の 1 人が対応可能になるのは最短で 20 時間後です。会社 B も 5 マイル離れており、評価は 4 ですが、従業員の 1 人が対応可能になるのは最短で 5 時間後です。
したがって、ソート結果は B、A である必要があります。
各データに特別な重みを追加したいので、後で custom_score スクリプトで使用できる集計を書き始めました。
インデックスの作成、データのインポート、検索の完全な概要
現在、実際に結果を返すクエリを作成できましたが、可用性集約バケットは空です。ただし、返される結果が構造化されすぎているため、フラット化したいと考えています。
現在、返されるもの:
企業ID -> 従業員ID -> 最初の利用可能
次のような集計をしたいと思います:
企業ID -> 最初の利用可能
この方法では、スクリプトを実行してスコアを計算し、適切に並べ替えることができますcustom_score
。
より単純な質問:
複数レベルの (孫) 子で並べ替え/集計し、結果をフラット化するにはどうすればよいでしょうか。
ベストアンサー1
これを行うには集計は必要ありません。
並べ替えの基準は次のとおりです。
- 距離 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
、リクエスト時間とヒット内の各可用性の間の時間差を取得します。(次に、 を3 番目の並べ替え基準として_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
(最大逆数従業員1人あたりの利用可能までの時間、および最大の逆数(?)利用可能な従業員数(会社あたり)
これらすべてをまとめると、私たちは引き続き質問します会社しかし、使用会社 > 従業員 > 空き状況を生成する_score
ために使用する#3並べ替え基準:
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" }
}
}