LoginSignup
0
0

More than 1 year has passed since last update.

Mongo DB の入れ子構造で $unset

Last updated at Posted at 2022-05-31

前置き

あまり設計に慣れておらず,ややこしい(?)入れ子構造でデータを作ってしまい,データ修正に困ったので,覚え書き.

DB 構造

[
{
    scores: [
        {
            player_id: "user1"
            point: 10,
            events: [
                {
                    player_id: "user1"
                    id_in_another_collection: "foobar",
                    img_id: "imageimage"
                }
        },
        {
            player_id: "user2"
            point: 30,
            events: [
                {
                    player_id: "user2"
                    id_in_another_collection: "barfoo",
                    img_id: "imageimage2"
                }
                {
                    player_id: "user2"
                    id_in_another_collection: "barfoobar",
                    img_id: "imageimage3"
                }
            ]
        }
    ],
    other_data: "others...",
},
{...},
 ...
]

player_idscores.$.event.$ で被っていることに気付いて,あとで $unset しようとして,ハマったお話です.

問題のややこしさ

見ての通り,最深部の player_id にたどり着くまでに
(all_records ->) record -> scores -> score -> events -> event -> player_id,すなわち,(array ->) object -> array -> object -> array -> object というややこしい手順を踏まなければならない...

解決策

db.scores.updateMany(
    {"scores.events.player_id": { $exists: true, $not: {$size: 0} }}, 
    {$unset: {"scores.$[].events.$[e].player_id": ""}}, 
    {"arrayFilters": [{"e.player_id": {$ne: null}}]})

第一引数

player_id が空でないレコードを抜き出している.後に arrayFilters を適用するので不要かも?

第二引数

$unset の指定.player_idunset します,という意.
"scores.$[].events.$[e].player_id"$[e] は identifier と呼ばれているもので,公式ドキュメント1 によれば,

The filtered positional operator $[] identifies the array elements that match the arrayFilters conditions for an update operation, e.g. db.collection.updateMany() and db.collection.findAndModify().

すなわち,指定したフィルタにマッチする配列のキーを与えてくれるそうです.

$[] は配列の全ての要素,という意味2

フィルタについては第三引数を参照.

第三引数

第二引数で取り上げたフィルタを指定.
e は,第二引数において $[e] と表記した配列キーが指定しているオブジェクトに対応する(event.$[e] = e).
"e.player_id" : {$ne: null} は,配列 event の任意の要素 e について,e.player_idnull でなければフィルタに引っかかる,という意味である.
このときに引っかかった $[e] (実体は 0, 1 などの配列キー)を第二引数で用いて $unset してくれる.

参考

  1. $[<identifier>] — MongoDB Manual

  2. $[] — MongoDB Manual

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