GAミント至上主義

Web Monomaniacal Developer.

Elasticsearchでsortに複数のscript条件を使う

以前↓の記事でやったようにFunctions Scoreで複数条件を組みあわせてscoreを作りソートをしていたが、 複雑になってきて限界がきた。

ElasticsearchのFunction score queryでBoolean値や日付をソートに使う - GAミント至上主義

scoreの限界

scoreは最終的に32bitのintの正の値する必要があること。

2つ3つぐらいなら、100とか1000とか位を分けてなんとかできたけど、例えば求人サイトの給料順にしようとすると日給の場合、万単位なので、それだけで5桁は必要になり、他との組み合わせはかなり難しい。

負の値は使えないのも不便。

さらに募集集中、停止中、などなど他の条件が増えてくると厳しい。

複数sort

最初からそうすればよかったのだけど、リスエスト時のsortにscriptを使えた。

scriptの中はfunction scoreと同様に書ける。

さらにsortは配列にできるので↓のような感じにする。 フラグ系も0、1にしてtypeはnumberにそろえている。 求人サイトでは更新日からの日数、給料などでやっている。

[
  {
    "_script": {
      "type": "number",
      "script": {
        "lang": "painless",
        "source": "# 数字返すスクリプト"
      },
      "order": "asc"
    }
  },
  {
    "_script": {
      "type": "number",
      "script": {
        "lang": "painless",
        "source": "# 数字返すスクリプト"
      },
      "order": "asc"
    }
  },
  {
    "_script": {
      "type": "number",
      "script": {
        "lang": "painless",
        "source": "# 数字返すスクリプト"
      },
      "order": "asc"
    }
  },
  {
    "_script": {
      "type": "number",
      "script": {
        "lang": "painless",
        "source": "# 数字返すスクリプト"
      },
      "order": "asc"
    }
  }
]

レスポンスのhitsをconsole.log(body.hits.hits.map((hit) => hit.sort))出すとこんな感じ。

[
  [ 1, 0, 1, 132 ], [ 1, 0, 1, 132 ],
  [ 1, 0, 1, 133 ], [ 1, 0, 1, 133 ],
  [ 1, 0, 1, 136 ], [ 1, 0, 1, 136 ],
  [ 1, 0, 1, 136 ], [ 1, 0, 1, 136 ],
  [ 1, 0, 1, 139 ], [ 1, 0, 1, 199 ],
  [ 1, 1, 0, 297 ], [ 1, 1, 0, 483 ],
  [ 1, 1, 0, 786 ], [ 1, 1, 0, 832 ],
  [ 0, 0, 0, 460 ], [ 0, 0, 0, 460 ],
  [ 0, 1, 0, 460 ], [ 0, 1, 0, 460 ]
]

あんまり複雑だったり、多かったりするとCPUを喰いそうだけど、今のところ大きな差はないので大丈夫そう