結論:orderByは指定フィールドの存在でもフィルタリングする
FirestoreのorderBy()句は、指定したフィールドが存在しないドキュメントを自動的に除外する。
並べ替えだけでなく、暗黙的にフィルタリングも行うため、予期しないデータ欠落が発生する可能性がある。
問題:orderByで結果が減る
// 「createdAt」フィールドでソート
query := client.Collection("users").OrderBy("createdAt", firestore.Asc)このクエリでは、createdAtフィールドが存在しないドキュメントは結果に含まれない。
例:
- ✅
{id: 1, name: "Alice", createdAt: "2025-01-01"}→ 結果に含まれる - ❌
{id: 2, name: "Bob"}→ 結果から除外される(createdAtがない)
公式ドキュメントの記載
orderBy() 句は、指定したフィールドの有無によるフィルタも行います。指定したフィールドがないドキュメントは結果セットには含まれません。
Cloud Firestore でデータを並べ替えたり制限する | Firebase
範囲比較との組み合わせ制約
範囲比較(<, <=, >, >=)のフィルタがある場合、最初のorderBy()は同じフィールドで行う必要がある。
// ❌ NG: 範囲比較(age)と異なるフィールド(name)で最初にorderBy
query := client.Collection("users").
Where("age", ">", 20).
OrderBy("name", firestore.Asc)
// エラー: 最初のorderByはageにする必要がある
// ✅ OK: 範囲比較と同じフィールド(age)で最初にorderBy
query := client.Collection("users").
Where("age", ">", 20).
OrderBy("age", firestore.Asc).
OrderBy("name", firestore.Asc)対策:フィールド存在を意識する
1. デフォルト値を設定
// ドキュメント作成時に必ずcreatedAtを設定
user := map[string]interface{}{
"name": "Alice",
"createdAt": time.Now(),
}2. フィールド存在チェック
// 存在しないフィールドでのソートは避ける
// または、存在チェックのWhere句を追加(複合インデックス必要)
3. 複合インデックスを作成
範囲比較と複数フィールドでのソートを行う場合、複合インデックスが必要。
まとめ
orderBy()は並べ替えだけでなく、指定フィールドの存在でもフィルタリングする- 指定フィールドが存在しないドキュメントは結果から除外される
- 範囲比較がある場合、最初の
orderBy()は同じフィールドで行う必要がある - ドキュメント作成時にソート用フィールドを必ず設定することを推奨
