LoginSignup
0
0

Aerospike Go Clientで複数条件を設定したい

Posted at

はじめに

Aerospike Go Clientを利用している箇所で改修をする際につまづいたところがあるのでまとめます

問題

Aerospikeで日付でフィルタリングをしていたのですが、そこから別の条件をANDで検索したレコードすべてをほしいなと思ったのですが、なかなかできずに困りました

	// クエリのステートメントを設定します。
	stmt := as.NewStatement("namespace", "set")

	// 時間範囲をUnixタイムスタンプに変換します。
	fromTimestamp := time.Date(2023, 6, 1, 0, 0, 0, 0, time.UTC).Unix()
	toTimestamp := time.Date(2023, 6, 30, 0, 0, 0, 0, time.UTC).Unix()

	// タイムスタンプの範囲フィルタを設定します。
	stmt.SetFilters(as.NewRangeFilter("timestamp", fromTimestamp, toTimestamp))

    // ここで、別の条件も追加したい

	// クエリを実行し、結果のレコードを取得します。
	recordSet, err := client.Query(nil, stmt)
	if err != nil {

stmt.SetFiltersをもう一つ用意しようとしましたが、上書きされてしまうので実現しませんでした

わかったこと

ChatGPTにきいたところ以下のことがわかりました

Aerospikeのクエリエンジンは、1つのインデックスに対して1つの範囲フィルターしか許容しないため、複数フィールドのAND条件を直接適用することはできません

そもそも複数条件で検索することが機能的にできませんでした

回避策1

AerospikeのUser-Defined Function (UDF) という機能を利用することで複数条件のようなことができます

filter_by_application.lua
function filter_by_application(rec)
    if rec['application'] == 'app' then
        return true
    else
        return false
    end
end

このようなluaを書いてサーバーに登録して使います

stmt.SetAggregateFunction("application_filter", "filter_by_application", nil, true)

サーバーに追加しないといけないので動いているサーバーに追加するというのは大変です

回避策2

Goで制御する

		if appVal, exists := res.Record.Bins["application"]; exists {
			if appVal == "app" {
				fmt.Println(res.Record)
			}
		}

大規模なデータでは時間がかかるのがネックです

おわりに

今回はGo側に制御コードをいれることで回避しました

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0