MongoDB(13) - 検索編(ソート)

今回はソートと検索件数の制限を行います。

サンプルデータ

次のようなデータをcol1コレクションに設定します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
> db.col1.insertOne({name:'高山', age:20})
{
"acknowledged" : true,
"insertedId" : ObjectId("6125c3fc15504c166c7ec86f")
}

> db.col1.insertOne({name:'生田', age:11})
{
"acknowledged" : true,
"insertedId" : ObjectId("6125c3fc15504c166c7ec870")
}

> db.col1.insertOne({name:'菅井', age:34})
{
"acknowledged" : true,
"insertedId" : ObjectId("6125c3fc15504c166c7ec871")
}

> db.col1.insertOne({name:'武本', age:58})
{
"acknowledged" : true,
"insertedId" : ObjectId("6125c3fc15504c166c7ec872")
}

> db.col1.insertOne({name:'上村', age:41})
{
"acknowledged" : true,
"insertedId" : ObjectId("6125c3fc15504c166c7ec873")
}

> db.col1.find()
{ "_id" : ObjectId("6125c3fc15504c166c7ec86f"), "name" : "高山", "age" : 20 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec870"), "name" : "生田", "age" : 11 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec871"), "name" : "菅井", "age" : 34 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec872"), "name" : "武本", "age" : 58 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec873"), "name" : "上村", "age" : 41 }

ソート

検索結果をソートするためには、sortを使います。

sortの引数にソートするキーと昇順・降順を指定します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1:昇順ソート
> db.col1.find().sort({age:1})
{ "_id" : ObjectId("6125c3fc15504c166c7ec870"), "name" : "生田", "age" : 11 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec86f"), "name" : "高山", "age" : 20 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec871"), "name" : "菅井", "age" : 34 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec873"), "name" : "上村", "age" : 41 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec872"), "name" : "武本", "age" : 58 }

# -1:降順ソート
> db.col1.find().sort({age:-1})
{ "_id" : ObjectId("6125c3fc15504c166c7ec872"), "name" : "武本", "age" : 58 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec873"), "name" : "上村", "age" : 41 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec871"), "name" : "菅井", "age" : 34 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec86f"), "name" : "高山", "age" : 20 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec870"), "name" : "生田", "age" : 11 }

件数制限

検索結果が多すぎると、結果がなかなか返ってこないということがあります。

そのような場合は、limitを使って取得する件数を制限します。

[Mongoシェル]

1
2
3
4
5
# 3件だけ取得
> db.col1.find().limit(3)
{ "_id" : ObjectId("6125c3fc15504c166c7ec86f"), "name" : "高山", "age" : 20 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec870"), "name" : "生田", "age" : 11 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec871"), "name" : "菅井", "age" : 34 }

取得開始位置を指定

ページング処理をする場合、検索結果の11番目から20番目だけを取得したいということがありまs。

skipを使うと、取得の開始位置を指定することができます。

1番目のドキュメントの場合は0,2番目のドキュメントを指定する場合は1を指定します。
(0からのカウントになるので注意してください。)

[Mongoシェル]

1
2
3
4
5
# 検索結果の3番目以降を取得
> db.col1.find().skip(2)
{ "_id" : ObjectId("6125c3fc15504c166c7ec871"), "name" : "菅井", "age" : 34 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec872"), "name" : "武本", "age" : 58 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec873"), "name" : "上村", "age" : 41 }

sort / limit / skipを組み合わせて検索

今回紹介したsortlimitskipは、組み合わせて使用することができます。

例えば、ageで昇順ソートし検索結果の2番目から3件取得する場合は次のようになります。

[Mongoシェル]

1
2
3
4
> db.col1.find().sort({age:1}).skip(1).limit(3)
{ "_id" : ObjectId("6125c3fc15504c166c7ec86f"), "name" : "高山", "age" : 20 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec871"), "name" : "菅井", "age" : 34 }
{ "_id" : ObjectId("6125c3fc15504c166c7ec873"), "name" : "上村", "age" : 41 }

Pythonで操作

上記の検索をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pymongo
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 昇順ソート
for doc in db1.col1.find().sort('age', pymongo.ASCENDING):
print(doc)

# 降順ソート
for doc in db1.col1.find().sort('age', pymongo.DESCENDING):
print(doc)

# 3件だけ取得
for doc in db1.col1.find().limit(3):
print(doc)

# 検索結果の3番目以降を取得
for doc in db1.col1.find().skip(2):
print(doc)

# ageで昇順ソートし検索結果の2番目から3件取得
for doc in db1.col1.find().sort('age', pymongo.ASCENDING).skip(1).limit(3):
print(doc)

MongoDBの検索に関する動作確認は以上です。

次回からは、MongoDBの更新に関する動作を確認していきます。

MongoDB(12) - 検索編(5回目)

今回は配列、オブジェクトの値で検索を行います。

サンプルデータ

次のようなデータをcol1コレクションに設定します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
> db.col1.insertOne({name:"鈴木",
age:28,
skill:["English", "Python", "MongoDB", "Driving"],
child:[
{name:"あゆみ", age:5},
{name:"えりこ", age:2}
]})
{
"acknowledged" : true,
"insertedId" : ObjectId("61240eff1c53d262d76db31a")
}

> db.col1.insertOne({name:"佐藤",
age:15,
skill:["Thailand", "Oracle", "AI"]
})
{
"acknowledged" : true,
"insertedId" : ObjectId("61240f001c53d262d76db31b")
}

> db.col1.find()
{ "_id" : ObjectId("61240eff1c53d262d76db31a"), "name" : "鈴木", "age" : 28, "skill" : [ "English", "Python", "MongoDB", "Driving" ], "child" : [ { "name" : "あゆみ", "age" : 5 }, { "name" : "えりこ", "age" : 2 } ] }
{ "_id" : ObjectId("61240f001c53d262d76db31b"), "name" : "佐藤", "age" : 15, "skill" : [ "Thailand", "Oracle", "AI" ] }

配列の要素数で検索

配列の要素数で検索する場合は、$sizeを使います。

skill配列の要素数が3のドキュメントを検索してみます。

[Mongoシェル]

1
2
> db.col1.find({skill:{$size:3}})
{ "_id" : ObjectId("61240f001c53d262d76db31b"), "name" : "佐藤", "age" : 15, "skill" : [ "Thailand", "Oracle", "AI" ] }

配列の中に指定した値をすべて持つかどうかを検索

配列の中に指定した値がすべて含まれているかどうかを検索する場合には、$allを使います。

skill配列にPythonDrivingの両方が含まれているドキュメントを検索してみます。

[Mongoシェル]

1
2
> db.col1.find({skill:{$all:["Python", "Driving"]}})
{ "_id" : ObjectId("61240eff1c53d262d76db31a"), "name" : "鈴木", "age" : 28, "skill" : [ "English", "Python", "MongoDB", "Driving" ], "child" : [ { "name" : "あゆみ", "age" : 5 }, { "name" : "えりこ", "age" : 2 } ] }

オブジェクトの値で検索

サンプルデータの1つ目のドキュメントには、child配列の中にオブジェクトが設定されています。

配列の中のオブジェクトを指定して検索する場合は、“child.age”のように指定して検索できます。

[Mongoシェル]

1
2
> db.col1.find({"child.age":5})
{ "_id" : ObjectId("61240eff1c53d262d76db31a"), "name" : "鈴木", "age" : 28, "skill" : [ "English", "Python", "MongoDB", "Driving" ], "child" : [ { "name" : "あゆみ", "age" : 5 }, { "name" : "えりこ", "age" : 2 } ] }

オブジェクトの中を検索条件にする場合は”(ダブルクォーテーション)でくくる必要がありますのでご注意下さい。

Pythonで操作

上記の検索をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 要素数で検索
for doc in db1.col1.find({'skill': {'$size':3}}):
print(doc)

# 配列の中に指定した値をすべて持つかどうかを検索
for doc in db1.col1.find({'skill':{'$all':["Python", "Driving"]}}):
print(doc)

# オブジェクトの値で検索
for doc in db1.col1.find({'child.age':5}):
print(doc)

次回はソートと検索件数の制限を行ってみます。

MongoDB(11) - 検索編(4回目)

今回は空文字/Null/フィールドなし/undefinedに関する検索を行います。

サンプルデータ

次のようなデータをcol1コレクションに設定します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> db.col1.insertOne({_id:1, name:""})
{ "acknowledged" : true, "insertedId" : 1 }

> db.col1.insertOne({_id:2, name:null})
{ "acknowledged" : true, "insertedId" : 2 }

> db.col1.insertOne({_id:3})
{ "acknowledged" : true, "insertedId" : 3 }

> db.col1.insertOne({_id:4, name:undefined})
{ "acknowledged" : true, "insertedId" : 4 }

> db.col1.find()
{ "_id" : 1, "name" : "" }
{ "_id" : 2, "name" : null }
{ "_id" : 3 }
{ "_id" : 4, "name" : undefined }

上記データを一覧にまとめると下記のようになります。

_idname
1""
2null
3(nameフィールドなし)
4undefined

空文字/Null/フィールドなし/undefinedの説明

各データの説明は以下の通りです。

  • 空文字
    0バイトの文字列です。空文字はString型として扱われます。
  • null
    nullはNull型として扱われます。
  • フィールドなし
    MongoDBではドキュメントごとにフィールドが異なります。
    そのためフィールド自体がないということがありえます。
  • undefined
    JavaScriptではundefinedという型があります。
    値がないけれどもnullでもないという特殊な型です。

Null検索

Null検索を行います。

[Mongoシェル]

1
2
3
4
> db.col1.find({name:null})
{ "_id" : 2, "name" : null }
{ "_id" : 3 }
{ "_id" : 4, "name" : undefined }

nameフィールドがnullのドキュメントだけではなく、nameフィールドのないドキュメントundedinedのドキュメントも検索対象となるので注意が必要です。

フィールドの存在有無検索($exists)

フィールドの存在有無を検索する$existsを使って検索してみます。

[Mongoシェル]

1
2
> db.col1.find({name:{$exists:false}})
{ "_id" : 3 }

$existsにfalseを指定すると、そのフィールドが存在しないドキュメントだけが検索されます。

データ型指定検索($type)

$typeにデータ型“null”を指定して検索を行います。

[Mongoシェル]

1
2
> db.col1.find({name:{$type:"null"}})
{ "_id" : 2, "name" : null }

nameフィールドがnullのドキュメントだけが検索対象となります。

String型であるかどうかを調べるためには“string”、配列型かどうかを調べるためには“array”を指定します。

その他のデータ型は下記の公式ページをご参照下さい。

MongoDB $typeのデータ型 - https://docs.mongodb.com/manual/reference/operator/query/type/

まとめ

上記の検索結果を一覧にまとめると下記のようになります。

“〇”が検索対象になるドキュメントで、”—“が検索対象にならないドキュメントです。

データ型Null検索$exists(false)検索$type("null")検索
空文字---------
Null型---
フィールドなし---
undefined-----

Pythonで操作

上記の検索をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# Null検索
for doc in db1.col1.find({'name': None}):
print(doc)

# フィールドの存在有無検索($exists)
for doc in db1.col1.find({'name': {'$exists':False} }):
print(doc)

# データ型指定検索($type)
for doc in db1.col1.find({'name': {'$type':'null'} }):
print(doc)

次回は配列、オブジェクトの値で検索を行います。

MongoDB(10) - 検索編(3回目)

今回はAND条件やOR条件を指定しての検索を行います。

サンプルデータ

次のようなデータがcol1コレクションに設定されています。

nameage
岡田30
山岡35
鈴木24

AND条件検索

AND条件で検索する場合は、$andを使います。

$andに検索条件を配列で指定します。検索条件は2つ以上指定できます。

[Mongoシェル]

1
2
3
4
5
6
> db.col1.find({$and:[
{name:"岡田"},
{age:{$gte:25}}
]
})
{ "_id" : ObjectId("6120958fdee0a016235653f8"), "name" : "岡田", "age" : 30 }

OR条件検索

OR条件で検索する場合は、$orを使います。

$orに検索条件を配列で指定します。検索条件は2つ以上指定できます。

[Mongoシェル]

1
2
3
4
5
6
7
> db.col1.find({$or:[
{name:"岡田"},
{age:{$gte:25}}
]
})
{ "_id" : ObjectId("6120958fdee0a016235653f8"), "name" : "岡田", "age" : 30 }
{ "_id" : ObjectId("6120958fdee0a016235653f9"), "name" : "山岡", "age" : 35 }

Pythonで操作

上記の操作をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# AND条件検索
for doc in db1.col1.find({'$and': [{'name':'岡田'}, {'age':{'$gte':25}}] }):
print(doc)

# OR条件検索
for doc in db1.col1.find({'$or': [{'name':'岡田'}, {'age':{'$gte':25}}] }):
print(doc)

次回は空文字/Null/フィールドなし/undefinedに関する検索を行います。

MongoDB(9) - 検索編(2回目)

今回は条件を指定した検索を行います。

サンプルデータ

次のようなデータがcol1コレクションに設定されています。

nameage
岡田30
山岡35
鈴木24

完全一致検索、部分一致検索

完全一致検索と部分一致検索を行います。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 完全一致検索
> db.col1.find({name:"岡田"})
{ "_id" : ObjectId("6120958fdee0a016235653f8"), "name" : "岡田", "age" : 30 }

# 部分一致検索
> db.col1.find({name:/岡/})
{ "_id" : ObjectId("6120958fdee0a016235653f8"), "name" : "岡田", "age" : 30 }
{ "_id" : ObjectId("6120958fdee0a016235653f9"), "name" : "山岡", "age" : 35 }

# 前方一致検索
> db.col1.find({name:/^岡/})
{ "_id" : ObjectId("6120958fdee0a016235653f8"), "name" : "岡田", "age" : 30 }

# 後方一致検索
> db.col1.find({name:/岡$/})
{ "_id" : ObjectId("6120958fdee0a016235653f9"), "name" : "山岡", "age" : 35 }

範囲指定検索

範囲を指定した検索を行います。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 30以下
> db.col1.find({age:{$lte:30}})
{ "_id" : ObjectId("6120958fdee0a016235653f8"), "name" : "岡田", "age" : 30 }
{ "_id" : ObjectId("6120958fdee0a016235653fa"), "name" : "鈴木", "age" : 24 }

# 30未満
> db.col1.find({age:{$lt:30}})
{ "_id" : ObjectId("6120958fdee0a016235653fa"), "name" : "鈴木", "age" : 24 }

# 30以上
> db.col1.find({age:{$gte:30}})
{ "_id" : ObjectId("6120958fdee0a016235653f8"), "name" : "岡田", "age" : 30 }
{ "_id" : ObjectId("6120958fdee0a016235653f9"), "name" : "山岡", "age" : 35 }

# 30より大きい
> db.col1.find({age:{$gt:30}})
{ "_id" : ObjectId("6120958fdee0a016235653f9"), "name" : "山岡", "age" : 35 }

# 27以上32以下
> db.col1.find({age:{$gte:27,$lte:32}})
{ "_id" : ObjectId("6120958fdee0a016235653f8"), "name" : "岡田", "age" : 30 }

Pythonで操作

上記の操作をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 完全一致検索
for doc in db1.col1.find({'name':'岡田'}):
print(doc)

# 部分一致検索
for doc in db1.col1.find({'name':{'$regex':'岡'}}):
print(doc)

# 前方一致検索
for doc in db1.col1.find({'name':{'$regex':'^岡'}}):
print(doc)

# 後方一致検索
for doc in db1.col1.find({'name':{'$regex':'岡$'}}):
print(doc)
#---------------------------------------------------
# 30以下
for doc in db1.col1.find({'age':{'$lte':30}}):
print(doc)

# 30未満
for doc in db1.col1.find({'age':{'$lt':30}}):
print(doc)

# 30以上
for doc in db1.col1.find({'age':{'$gte':30}}):
print(doc)

# 30より大きい
for doc in db1.col1.find({'age':{'$gt':30}}):
print(doc)

# 27以上32以下
for doc in db1.col1.find({'age':{'$gte':27, '$lte':32}}):
print(doc)

次回はAND条件やOR条件での検索を行います。

MongoDB(8) - 検索編

今回から検索に関する動作を確認していきます。

サンプルデータ

次のようなデータがcol1コレクションに設定されています。

nameage
岡田30
山岡35
鈴木24

全件検索・全フィールド表示

もっともシンプルな全件検索、全フィールド表示を行います。

(find関数に引数を設定しません)

[Mongoシェル]

1
2
3
4
> db.col1.find()
{ "_id" : ObjectId("611f72364894370583f311e6"), "name" : "岡田", "age" : 30 }
{ "_id" : ObjectId("611f72364894370583f311e7"), "name" : "山岡", "age" : 35 }
{ "_id" : ObjectId("611f72364894370583f311e8"), "name" : "鈴木", "age" : 24 }

全件検索・フィールド表示/非表示

全件検索は同じで、表示するフィールドを指定してみます。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
# _idフィールドを非表示
> db.col1.find({},{_id:0})
{ "name" : "岡田", "age" : 30 }
{ "name" : "山岡", "age" : 35 }
{ "name" : "鈴木", "age" : 24 }

# _idフィールドを非表示にし、nameフィールドを表示する
> db.col1.find({},{_id:0,name:1})
{ "name" : "岡田" }
{ "name" : "山岡" }
{ "name" : "鈴木" }

find関数に指定している引数の意味は次の通りです。

  • 第1引数
    検索条件を指定します。カラの場合は全てのドキュメントを表示します。
  • 第2引数
    表示するフィールドを指定します。
    表示するフィールドの場合は1、表示しないフィールドの場合は0を指定します。

Pythonで操作

上記の操作をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 全件表示
for doc in db1.col1.find():
print(doc)

# _idフィールドを非表示
for doc in db1.col1.find({},{'_id':0}):
print(doc)

# _idフィールドを非表示にし、nameフィールドを表示する
for doc in db1.col1.find({},{'_id':0, 'name':1}):
print(doc)

次回は条件(完全一致、部分一致)を指定して、検索の動作確認を行います。

MongoDB(7) - ドキュメント作成編(3回目)

今回はオブジェクト型のドキュメント追加を行ってみます。

オブジェクト型のドキュメント追加

オブジェクト型のドキュメントを追加します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
> db.col1.insertOne({name:"親",
child1: {name:"ゆめ", age:2},
child2: {name:"きぼう", age:1}})
{
"acknowledged" : true,
"insertedId" : ObjectId("611ec366681d069119256981")
}

> db.col1.find()
{ "_id" : ObjectId("611ec366681d069119256981"),
"name" : "親",
"child1" : { "name" : "ゆめ", "age" : 2 },
"child2" : { "name" : "きぼう", "age" : 1 } }

配列の中にオブジェクトがあるドキュメント追加

配列の中にオブジェクトがあるドキュメントを追加します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> db.col1.insertOne({name:"親",
children:[ {name:"ゆめ", age:2},
{name:"きぼう", age:1}]
})
{
"acknowledged" : true,
"insertedId" : ObjectId("611ec3ad681d069119256982")
}

> db.col1.find()
{ "_id" : ObjectId("611ec3ad681d069119256982"),
"name" : "親",
"children" : [ { "name" : "ゆめ", "age" : 2 },
{ "name" : "きぼう", "age" : 1 } ] }

Pythonで操作

上記の操作をPythonでまとめて行うと、次のようになります。

辞書型のデータを追加だけなのでとても簡単です。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# オブジェクト型のドキュメント追加
doc = {}
doc['name'] = '親'
doc['child1'] = {'name':'ゆめ', 'age':2}
doc['child2'] = {'name':'きぼう', 'age':1}
db1.col1.insert_one(doc)

# 全件表示
for x in db1.col1.find():
print(x)

# 配列の中にオブジェクトがあるドキュメント追加
doc = {}
doc['name'] = '親'
doc['children'] = []
doc['children'].append({'name':'ゆめ', 'age':2})
doc['children'].append({'name':'きぼう', 'age':1})
db1.col1.insert_one(doc)

# 全件表示
for x in db1.col1.find():
print(x)

Pythonでは辞書型がとても便利でよく使うと思いますが、その辞書型をさくさくとDBに追加できるMongoDBはとても相性のいいデータベースだと感じました。

次回からは検索に関する操作を行います。

MongoDB(6) - ドキュメント作成編(2回目)

今回はいろいろなデータ型のドキュメントと配列データをもつドキュメントの追加を行ってみます。

いろいろなデータ型のドキュメント追加

いろいろなデータ型のドキュメントを追加します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> db.col1.insertOne({stringData:"stringData",
doubleData:123.456,
intData:NumberInt(11),
longData:NumberLong(22),
decimalData:NumberDecimal(33.44),
dateData:ISODate("2021-10-10T12:34:56Z"),
booleanData:true,
nullData:null})
{
"acknowledged" : true,
"insertedId" : ObjectId("611c6dd47466ff972f94ccca")
}

> db.col1.find()
{ "_id" : ObjectId("611c6dd47466ff972f94ccca"),
"stringData" : "stringData",
"doubleData" : 123.456,
"intData" : 11,
"longData" : NumberLong(22),
"decimalData" : NumberDecimal("33.4400000000000"),
"dateData" : ISODate("2021-10-10T12:34:56Z"),
"booleanData" : true,
"nullData" : null }

配列データをもつドキュメントを追加

配列データをもつドキュメントを追加します。

(データ追加前にcol1コレクションを一旦削除しています。)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
> db.col1.drop()
true

> db.col1.insertOne({name:"親", children: ["子1", "子2"]})
{
"acknowledged" : true,
"insertedId" : ObjectId("611c704a7466ff972f94cccb")
}

> db.col1.find()
{ "_id" : ObjectId("611c704a7466ff972f94cccb"), "name" : "親", "children" : [ "子1", "子2" ] }

Pythonで操作

上記の操作をPythonでまとめて行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from pymongo import MongoClient
import bson
from datetime import datetime

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# いろいろなデータ型のドキュメント追加
data1 = {'stringData' : 'stringData',
'doubleData' : 123.456,
'intData' : 11,
'longData' : bson.int64.Int64('22'),
'decimalData': bson.decimal128.Decimal128('33.44'),
'dateData' : datetime(2021, 10, 10, 12, 34, 56),
'booleanData': True,
'nullData' : None}
db1.col1.insert_one(data1)

# 全件表示
for x in db1.col1.find():
print(x)

# 配列データをもつドキュメント追加
data1 = {'name':'親', 'children': ['子1', '子2']}
db1.col1.insert_one(data1)

# 全件表示
for x in db1.col1.find():
print(x)

次回はオブジェクト型のドキュメントを追加していきます。

MongoDB(5) - ドキュメント作成編

今回はMongoDBのドキュメント追加に関する操作を行ってみます。

ドキュメントはRDBのレコードに相当します。

1件のドキュメント追加

ドキュメントを1件追加する場合は、insertOne関数を使います。

ドキュメントを追加するコレクションはcol1です。

コレクション(col1)は作成していなくても自動で作成されます。

(便利な反面、意図しないコレクションを作成してしまう可能性がありますので、気を付けてください。)

[Mongoシェル]

1
2
3
4
5
6
7
8
> db.col1.insertOne({name:"佐藤", age:10})
{
"acknowledged" : true,
"insertedId" : ObjectId("611b0f607466ff972f94ccc6")
}

> db.col1.find()
{ "_id" : ObjectId("611b0f607466ff972f94ccc6"), "name" : "佐藤", "age" : 10 }

複数のドキュメント追加

ドキュメントを複数追加する場合は、insertMany関数を使います。

insertMany関数には、配列データを渡します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> db.col1.insertMany([
{name:"鈴木", age:12},
{name:"高橋", age:15},
{name:"中村", age:19}
])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("611b10127466ff972f94ccc7"),
ObjectId("611b10127466ff972f94ccc8"),
ObjectId("611b10127466ff972f94ccc9")
]
}

> db.col1.find()
{ "_id" : ObjectId("611b0f607466ff972f94ccc6"), "name" : "佐藤", "age" : 10 }
{ "_id" : ObjectId("611b10127466ff972f94ccc7"), "name" : "鈴木", "age" : 12 }
{ "_id" : ObjectId("611b10127466ff972f94ccc8"), "name" : "高橋", "age" : 15 }
{ "_id" : ObjectId("611b10127466ff972f94ccc9"), "name" : "中村", "age" : 19 }

Pythonで操作

上記の操作をPythonでまとめて行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# ドキュメント1件追加
data1 = {'name':'佐藤', 'age':10}
db1.col1.insert_one(data1)

# 全件表示
for x in db1.col1.find():
print(x)

# ドキュメント複数追加
data3 = [{'name':'鈴木', 'age':12},
{'name':'高橋', 'age':15},
{'name':'中村', 'age':19}]
db1.col1.insert_many(data3)

# 全件表示
for x in db1.col1.find():
print(x)

次回はいろいろなデータ型や配列データをドキュメントとして追加していきます。

MongoDB(4) - Cappedコレクション編

今回はMongoDBのCappedコレクションを作成します。

Cappedコレクションは、古いデータを自動で削除してくれるコレクションです。

ログ用のコレクションとしてよく使われます。

Cappedコレクション作成

Cappedコレクションの作成を行います。コレクション名はcap1とします。

Cappedコレクションを作成するときは、createCollectionコマンド実行時にオプションを指定します。

[Mongoシェル]

1
2
3
4
5
> use db1
switched to db db1

> db.createCollection("cap1", {capped:true, size:1024000, max:3})
{ "ok" : 1 }

上記ではサイズの上限(size)が1MB、ドキュメント数の上限(max)が3のCappedコレクションを作成しています。(サイズの単位はbyteとなります)

どちらかの上限に達したときに、古いデータが自動で削除されます。


作成したCappedコレクションの統計情報を確認してみます。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
> db.cap1.stats()
{
"ns" : "db1.cap1",
"size" : 0,
"count" : 0,
"storageSize" : 4096,
"freeStorageSize" : 0,
"capped" : true,
"max" : 3,
"maxSize" : 1024000,
(略)
}

対応するオプションは下記の通りで、正しく設定されていることが確認できます。

  • capped
    Cappedコレクションであるかどうか。
  • max
    ドキュメント数の上限値。
  • maxSize
    コレクションの最大サイズ。

Cappedコレクションの注意点

Cappedコレクションを使用する場合は、下記の3点に注意する必要があります。

  • サイズの上限を変更できない。
    もしサイズを変更したい場合は、新しいCappedコレクションを作成して、データを移行するという手順が必要になります。
  • データの削除・更新ができない。
    データが自動的に削除されていくことが前提にあるため、ドキュメントの削除・更新ができません。
  • シャーディングできない。
    Cappedコレクションをシャーディングすることはできません。
    (シャーディングとは、コレクションごとにデータを複数サーバ分散することができる機能です。)

Cappedコレクションの動作確認

ドキュメントの追加と検索の詳細操作は今後行う予定ですが、Cappedコレクションの動作を確認するためにすこし実行してみます。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# ドキュメントを3件追加
> db.cap1.insertOne({age:1})
{
"acknowledged" : true,
"insertedId" : ObjectId("611a3bcdbc6e53b3d72248e0")
}
> db.cap1.insertOne({age:2})
{
"acknowledged" : true,
"insertedId" : ObjectId("611a3bd4bc6e53b3d72248e1")
}
> db.cap1.insertOne({age:3})
{
"acknowledged" : true,
"insertedId" : ObjectId("611a3bd6bc6e53b3d72248e2")

# 全データを確認
> db.cap1.find()
{ "_id" : ObjectId("611a3bcdbc6e53b3d72248e0"), "age" : 1 }
{ "_id" : ObjectId("611a3bd4bc6e53b3d72248e1"), "age" : 2 }
{ "_id" : ObjectId("611a3bd6bc6e53b3d72248e2"), "age" : 3 }

# ドキュメントを1件追加
> db.cap1.insertOne({age:4})
{
"acknowledged" : true,
"insertedId" : ObjectId("611a3bf5bc6e53b3d72248e3")
}

# 全データを確認(古いデータが1件削除されていることが確認できる)
> db.cap1.find()
{ "_id" : ObjectId("611a3bd4bc6e53b3d72248e1"), "age" : 2 }
{ "_id" : ObjectId("611a3bd6bc6e53b3d72248e2"), "age" : 3 }
{ "_id" : ObjectId("611a3bf5bc6e53b3d72248e3"), "age" : 4 }

通常コレクションからCappedコレクションへの変更

通常のコレクションをCappedコレクションに変更することもできます。

cap2というコレクションをいったん作成し、それをCappedコレクションに変更してみます。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 通常コレクションを作成
> db.createCollection("cap2")
{ "ok" : 1 }

# 変更前のコレクションの統計情報を表示
> db.cap2.stats()
{
"ns" : "db1.cap2",
"size" : 0,
"count" : 0,
"storageSize" : 4096,
"freeStorageSize" : 0,
"capped" : false,
(略)
}

# 通常コレクションをCappedコレクションに変更
> db.runCommand({"convertToCapped":"cap2", size:1024, max:1})
{ "ok" : 1 }


# 変更後のコレクションの統計情報を表示
> db.cap2.stats()
{
"ns" : "db1.cap2",
"size" : 0,
"count" : 0,
"storageSize" : 4096,
"freeStorageSize" : 0,
"capped" : true,
"max" : 0,
"maxSize" : 1024,
(略)
}

上記では、サイズの上限が1024バイトでドキュメント数の上限が1のCappedコレクションに変換しています。

統計情報を見ると、cappedオプションがtrueになりサイズの上限(maxSize)が1024になっていることが確認できます。

ただし、ドキュメント数の上限値(max)が1になっていません。

調べたところCappedコレクションへの変更を行うときmaxオプション(ドキュメント数の上限値)は指定できるものの、コレクションに反映することができないという謎仕様があるとのことです。

Cappedコレクションの変更コマンドは使わずに、新規でCappedコレクションを作成しデータの移行をした方が安全かもしれません😅😅