3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MongoDB 3.6 でコレクションに制約を付ける

Posted at

#MongoDBの制約

MongoDBのコレクションに必須項目などの制約を設けたい時があります。制約の付け方については公式ドキュメントに例があるんですけど、色々とカバーしてある分、初見ではなかなか分かりづらいんですよね。

ここでは最小構成として、例えばオラクルで言うところの「NOT NULL」制約を設けたいと思います。MongoDBの言葉では「required」制約ですね。

#コレクション作成時に設定する場合

DBバージョン3.6からはjson Schemaを使用できます。使うのは$jsonSchemaという演算子ですね。

ここではtestというデータベースを使います。createCollectionメソッドを使って明示的にコレクション作成しますが、その際にvalidatorにて制約を設定してみます。

> use test
switched to db test

> db.createCollection("project_d", {validator: {$jsonSchema: {required: ["name"]}}})
{ "ok" : 1 }

上記の例ではnameを必須項目としています。設定の確認はgetCollectionInfosメソッドで行えます。jsonのツリーが深くて見にくいのですが(笑)、nameがrequiredに含まれているっぽい事が分かります。

> db.getCollectionInfos({name: "project_d"})
[
        {
                "name" : "project_d",
                "type" : "collection",
                "options" : {
                        "validator" : {
                                "$jsonSchema" : {
                                        "required" : [
                                                "name"
                                        ]
                                }
                        }
                },
                "info" : {
                        "readOnly" : false,
                        "uuid" : UUID("7fa2aca9-42f7-4660-b276-bce2e75f0f3a")
                },
                "idIndex" : {
                        "v" : 2,
                        "key" : {
                                "_id" : 1
                        },
                        "name" : "_id_",
                        "ns" : "test.project_d"
                }
        }
]

次は動作確認です。nameを含まないドキュメントを挿入してみます。

> db.project_d.insertOne({_id: 0})
2018-01-02T18:18:16.287-0800 E QUERY    [thread1] WriteError: Document failed validation :
WriteError({
        "index" : 0,
        "code" : 121,
        "errmsg" : "Document failed validation",
        "op" : {
                "_id" : 0
        }
})
...

うまく弾かれてくれました。必須項目を含める事でちゃんと挿入できます。

> db.project_d.insertOne({_id: 0, name: "takumi", role: "downhill"})
{ "acknowledged" : true, "insertedId" : 0 }

> db.project_d.find()
{ "_id" : 0, "name" : "takumi", "role" : "downhill" }

#既存コレクションに追加する場合

後から制約を設ける場合には、runCommandメソッドを使います。チームにおける役割をはっきりさせるのは重要ですので、上の例の「role」を必須項目にしてみましょう。

> db.runCommand({collMod: "project_d", validator: {$jsonSchema: {required: ["name", "role"]}}})
{ "ok" : 1 }

> db.getCollectionInfos({name: "project_d"})
[
        {
                "name" : "project_d",
                "type" : "collection",
                "options" : {
                        "validator" : {
                                "$jsonSchema" : {
                                        "required" : [
                                                "name",
                                                "role"
                                        ]
                                }
                        },
                        "validationLevel" : "strict",
                        "validationAction" : "error"
                },
                "info" : {
                        "readOnly" : false,
                        "uuid" : UUID("7fa2aca9-42f7-4660-b276-bce2e75f0f3a")
                },
                "idIndex" : {
                        "v" : 2,
                        "key" : {
                                "_id" : 1
                        },
                        "name" : "_id_",
                        "ns" : "test.project_d"
                }
        }
]

設定できたようです。そしたら新しいデータを入れてみます。

> db.project_d.insertOne({_id: 1, name: "keisuke"})
2018-01-02T18:29:47.788-0800 E QUERY    [thread1] WriteError: Document failed validation :
WriteError({
        "index" : 0,
        "code" : 121,
        "errmsg" : "Document failed validation",
        "op" : {
                "_id" : 1,
                "name" : "keisuke"
        }
})
...

> db.project_d.insertOne({_id: 1, name: "keisuke", role: "hillclimb"})
{ "acknowledged" : true, "insertedId" : 1 }

roleを省いた方はちゃんと弾かれておりますね。

今回は最小構成で動かす事を意識してrequired制約だけを実装してみましたが、json Schemaの中では、データ型の指定など、種々のvalidationもかける事ができます。必要に応じてincrementalに実験して行きたい所存です。

3
3
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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?