0
1

【MongoDB】ソート対象列でnull値があった場合に末尾にしたい

Posted at

概要

例えばPostgreSQLではORDER BY句において、7.5. 行の並べ替え(ORDER BY)のドキュメントにある通り、NULLS FIRSTNULLS LASTで、ソートにおけるnull値の位置を設定できます。
MongoDBでは2023年11月時点においては、そのような設定は無いようです。では、null値の位置を明示的に設定するにはどうしたらよいか、というのを今回メモ書きします。

対応方針

やり方は色々考えられると思いますが、How to sort null value at the end while in Ascending MongoDBのstackoverflowの回答に書かれている内容が、良いかなと感じました。
対応方針としては、aggregateにおいてソート用のフィールドを設けて、nullの場合は$ifNull句で後ろにくるような数値を設定し、その後ソートします。

実装サンプル

Goで実装した内容を以下に記します。Go以外でも同様のクエリで期待した結果が得られると思います。

func SampleSortQuery(userAccountId string) ([]modelDb.ResultEntity, error) {
	ctx, _ := context.WithTimeout(context.Background(), 20*time.Second)
	c, err := mongo.Connect(ctx, options.Client().ApplyURI(os.Getenv("DB_CONNECTION")))
	col := c.Database(os.Getenv("DB_NAME")).Collection("sample_collection")
	if col == nil {
		panic(errors.New("can not get collection"))
	}
	var docs []modelDb.ResultEntity

    // ここからクエリの内容
	matchStage := bson.M{"$match": bson.M{
		"user_account_id": userAccountId},
	}
	// display_orderのフィールドで基本ソートするがnullの場合は末尾にする
	addSortStage := bson.M{"$addFields": bson.M{
		"sort_field": bson.M{"$ifNull": bson.A{"$display_order", math.MaxInt32}}},
	}
	sortStage := bson.M{"$sort": bson.M{
		"sort_field": 1},
	}
	projectStage := bson.M{"$project": bson.M{
		"_id":                1,
		"name":               1,
		"description":        1,
	}}

	cur, err := col.Aggregate(context.Background(),
		[]bson.M{
			matchStage, addSortStage, sortStage, projectStage,
		})
	if err != nil {
		return docs, err
	}

	for cur.Next(context.Background()) {
		var doc modelDb.ResultEntity
		if err = cur.Decode(&doc); err != nil {
			return nil, err
		}
		docs = append(docs, doc)
	}
	return docs, nil
}
0
1
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
1