Firestore のトランザクションが守るのは読んだ文書だけ

結論 Firestore のトランザクションが競合として扱うのは、その中で tx.Get した文書だけ。 トランザクションの外で読んだ値、読まずに書いた文書、クエリで「無かった」ことは守らない 悲観 (Standard の既定) と楽観 (Enterprise の既定) で違うのは決着の時点だけで、守る範囲は同じ。 判定に使う値をコールバックの中で読み直せば、同じコードがどちらでも通る 「1 件だけ」を守りたい値はドキュメント ID にして名指しで読む。件数を数える判定は、エミュレータでも条件次第で 2 件できた SDK はコールバックの中での生のクライアントの書き込みも、外側の ctx で張った RunTransaction も止めない。どちらもトランザクションの外で確定する 複数の文書を「全部か、無しか」で書くなら RunTransaction。BulkWriter はアトミックでない 以下は cloud.google.com/go/firestore v1.26.0 / Firestore エミュレータ v1.22.0 / Go 1.26.4 で実測した。 エミュレータは --database-edition=standard と --database-edition=enterprise の 2 つを立てた。 本番の Firestore では試していない。 前提: 競合として扱うのは、トランザクション内で読んだ文書だけ 公式ドキュメントは、並行制御の 2 つの方式をどちらも「読んだ文書」で説明している ( Data contention in transactions )。 悲観: “transactions place locks on the documents they read” 楽観: 読んだ文書を追跡し、“only if none of those documents changed” のときだけ書き込みを確定する 読んでいない文書はロックも照合もされない。 書くだけの文書、トランザクションの外で読んだ値、クエリの結果に入らなかった文書は、守る対象に入らない。 以下の節は、どれもこの 1 点から出てくる。 ...

2026-10-08 ·  2026-10-08 · 7 分 · 1290 文字

Go の Firestore SDK で消える項目と通らない値

結論 Go の Firestore SDK は、struct とドキュメントの間で項目を消しても、読み飛ばしてもエラーを返さない 書く側: Set は文書を丸ごと置き換える。serverTimestamp の項目は非ゼロだと書かれないので、読んで詰め直した Set で作成日時が消える。MergeAll は map 専用で、map の中の struct は丸ごと置き換わる。omitempty は false / 0 / ゼロ時刻を消し、struct は消さない 読む側: DataTo は struct に無いキーを捨てる。null を string や int に読んでも何もしない。int には整数で表せる double は入り、文字列は入らない 通らない値: ID・日時・クエリの値の規則を、SDK は一部しか検査しない。ID の規則違反は読みと書きで違うエラーになり、不正な UTF-8 を where に渡すと期限まで返ってこない 書き込みの経路ごとに、エミュレータで実際の文書を読んで確かめる 以下は cloud.google.com/go/firestore v1.26.0 / Firestore エミュレータ v1.22.0 / Go 1.26.4 で実測した。 本番の Firestore では試していない。 前提: 書き込み API ごとに書く範囲が違う ...

2026-10-03 ·  2026-10-03 · 7 分 · 1463 文字

FirestoreのorderByには暗黙のフィルタがある

結論: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. 複合インデックスを作成 範囲比較と複数フィールドでのソートを行う場合、複合インデックスが必要。 ...

2025-11-18 ·  2025-11-18 · 1 分 · 103 文字

Go言語omitemptyの罠:falseが保存できない

結論:omitemptyは便利だが罠がある omitemptyタグは空値を省略できて便利だが、falseや0が保存できなくなる罠がある。 特にboolean型で**「false」と「未設定」を区別したい場合は要注意**だ。 omitemptyとは 空値の場合にフィールドを省略するタグ。JSON/Firestoreへの保存時にデータサイズを削減できる。 type User struct { Name string `json:"name"` Email string `json:"email,omitempty"` // 空なら省略 } ⚠️ 最大の罠:「空」とみなされる値 以下の値は「空」として扱われ、omitempty付きフィールドから消える: 型 空とみなされる値 保存できない値の例 真偽値 false ❌ falseが保存不可 数値 0 ❌ 0が保存不可 文字列 "" ❌ 空文字列が保存不可 スライス/マップ nil または長さ0 ❌ 空配列が保存不可 ポインタ nil - time.Timeのゼロ値は、JSONでは「空」に当たらず消えない。下の「struct と time.Time は omitempty で消えない」を参照。 実例:boolean型の罠 問題のあるコード type Config struct { EnableFeature bool `firestore:"enableFeature,omitempty"` } config := Config{EnableFeature: false} // ❌ Firestoreに保存されない! // "enableFeature"フィールド自体が消える これでは「false」と「未設定」が区別できない。 ...

2025-10-27 ·  2026-10-03 · 2 分 · 372 文字

Firestore MongoDB互換の要点まとめ

Firestore MongoDB互換の要点まとめ 概要 Googleが「Firestore with MongoDB compatibility」を 発表 MongoDB用ドライバやMQL(MongoDB Query Language)をそのまま使ってFirestoreを操作可能 Firestoreのスケーラブルな基盤の上にMongoDB互換レイヤーを構築 現時点ではEnterpriseエディションのPreview機能 仕組み MongoDBクエリをFirestore内部クエリに変換する互換APIレイヤーを提供 collection.find() などのMongoDBドライバ呼び出しをそのまま利用可能 MongoDB→Firestoreへのクエリ変換処理で、未対応や制限付きの演算子が存在 Firestoreのインデックス構造に基づいて最適化されるが、MongoDBとは挙動が異なる クエリ互換性 基本的なクエリ(比較、論理、範囲、配列など)は概ね対応 複雑なAggregation Pipeline、ジオクエリ、テキスト検索($text)などは未対応または制限あり $regex など一部の正規表現検索は動作する可能性があるが完全な互換ではない $where、$lookupなどのサーバーサイドスクリプト・結合系クエリは非対応 like検索・部分一致 MongoDBでは $regex で部分一致検索が可能 Firestoreネイティブでは前方一致(prefix検索)のみ対応 MongoDB互換モードでも正規表現機能は一部制限あり 任意の位置一致や複雑な正規表現検索は非対応または非推奨 制限・注意点 現時点でPreview段階のためAPI変更の可能性あり MongoDBすべての演算子を網羅していない Firestore独自のクエリ制限(フィルター数上限など)は引き継がれる 同一クエリでもMongoDBより遅くなるケースあり(インデックス構造差による) リアルタイム更新やオフライン対応などFirestore特有の機能との完全互換は未実装 利用上の位置づけ MongoDBからFirestoreへの移行を容易にするための互換レイヤー 機能完全再現ではなく、移行コスト低減が主目的 高度な全文検索や結合が必要な場合はMongoDB本体を利用すべき Refs https://cloud.google.com/blog/products/databases/announcing-firestore-with-mongodb-compatibility https://cloud.google.com/firestore/mongodb-compatibility/docs/overview https://firebase.google.com/docs/firestore/enterprise/migrate-to-firestore-with-mongodb https://medium.com/@aswinalexandersam/firestore-with-mongodb-compatibility-current-state-limitations-and-opportunities-fbf03542d0c3 https://dev.to/franckpachot/firestore-with-mongodb-compatibility-testing-pagination-queries-jmf https://stackoverflow.com/questions/79631546/the-query-limitation-with-max-30-filter-parameters-still-exists-in-gcp-firestore

2025-10-17 ·  2025-10-17 · 1 分 · 50 文字