MongoDB(42) - テキストインデックスの作成/TTLインデックスの作成

テキストインデックスの作成とTTLインデックスの作成を行います。

テキストインデックスの作成

testコレクションのnameフィールドにテキストインデックスを作成します。

テキストインデックスを作成する場合は、“text”を指定します。

[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.test.createIndex({name:"text"})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : false,
"ok" : 1
}

// インデックスの確認
> db.test.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "name_text",
"weights" : {
"name" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
}
]

“name_text”というテキストインデックスを作成することができました。

TTLインデックスの作成

TTLインデックスを作成するためにはexpireAfterSecondsに秒数を指定します。

TTLインデックスに指定できるのは、Date型またはDate型を含む配列のフィールドです。

expireAfterSecondsで指定した秒数が経過したドキュメントを自動で削除することができます。

[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
37
38
39
// Dateフィールドを持つドキュメント作成
> db.ttltest.insert({time : ISODate("2021-06-09T10:20:05Z") } )
WriteResult({ "nInserted" : 1 })

// 作成したドキュメント確認
> db.ttltest.find()
{ "_id" : ObjectId("614bb5956e9eb9350501ee38"), "time" : ISODate("2021-06-09T10:20:05Z") }

// TTLインデックス作成
> db.ttltest.createIndex({time:1}, {expireAfterSeconds:60})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : false,
"ok" : 1
}

// 作成したTTLインデックスの確認
> db.ttltest.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"time" : 1
},
"name" : "time_1",
"expireAfterSeconds" : 60
}
]

// 60秒後にデータが自動削除されることを確認
> db.ttltest.find()

ttltestコレクションのtimeフィールドに、60秒でドキュメントが削除されるようにTTLインデックスを作成しました。

これでドキュメントが60秒経過後に自動的に削除されるようになります。

MongoDB(41) - インデックスの再構築

インデックスの再構築を行うと、コレクションにあるすべてのインデックスを一旦削除してインデックスを作り直します。

インデックスを再構築する理由は次の通りです。

  • データの追加や削除を行っていくうちに発生するインデックスの無駄を解消する。
  • ディスクの使用量を少なくする。

インデックスの再構築

インデックスの再構築にはreIndex()を使用します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> db.group.reIndex()
{
"nIndexesWas" : 1,
"nIndexes" : 1,
"indexes" : [
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
}
],
"ok" : 1
}

groupコレクションに対してインデックスの再構築を行うことができました。


次回は、テキストインデックスの作成とTTLインデックスの作成を行います。

MongoDB(40) - インデックスの削除

今回は、インデックスの削除を行います。

インデックスの削除

インデックスの削除にはdropIndexを使用します。

第1引数にはインデックス名を指名します。

(インデックス名はgetIndexesで取得できるnameフィールドの値です。)

[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.position.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "name_1"
}
]

> db.position.dropIndexes("name_1")
{ "nIndexesWas" : 2, "ok" : 1 }

> db.position.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]

positionコレクションのname_1インデックスを削除することができました。

次回は、インデックスの再構築を行います。

MongoDB(39) - インデックス作成のオプション

今回は、インデックス作成のオプションを確認します。

インデックス作成時のオプション

インデックスを作成する時には、オプション指定することができます。

オプションの一覧は下記の通りです。

項目名説明
backgroundバックグラウンドでインデックスを作成します。
デフォルトはfalseです。
nameインデックス名を指定します。
uniquetureを指定するとユニークインデックスを作成します。
ユニークインデックスにすると、nullは入れられません。
デフォルトはfalseです。
partialFilterExpressionフィルターを作成し、フィルターに一致したドキュメントの部分インデックスを作成します。
フィルターには以下の条件を設定できます。
・等式(key:valueまたは$eq)
$exists (trueのみ)
$gt, $gte, $lt, $lte
$type
$and

インデックスに名前を付けて、バックグラウンドで作成

memberコレクションに対して、インデックス名を”index_e_id”とし、バックグラウンドでインデックスを作成すると下記のようになります。

インデックスのオプションはcreateIndexの第2引数に指定します。

[Mongoシェル]

1
2
3
4
5
6
7
> db.member.createIndex({e_id:1}, {name:'index_e_id', background:true})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : true,
"ok" : 1
}

部分インデックスの作成

memberコレクションに対して、所属(group)が”開発1部”のドキュメントだけに対してインデックスを作成すると下記のようになります。

[Mongoシェル]

1
2
3
4
5
6
7
> db.member.createIndex({e_id:1}, {partialFilterExpression:{group:"開発1部"}})
{
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"createdCollectionAutomatically" : false,
"ok" : 1
}

次回は、インデックスの削除を行います。

MongoDB(38) - インデックスの確認・作成

インデックスの確認と作成を行います。

インデックスの確認

memberコレクションのインデックスを確認します。

インデックスの確認にはgetIndexes()を使用します。

[Mongoシェル]

1
2
> db.member.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]

_idフィールドに昇順(=1)のインデックスが作成されていることが分かります。

インデックス名(name)は_id_です。

これは自動的に作成されるデフォルトインデックスです。

インデックスの作成

memberコレクションにインデックスを作成します。

インデックスの作成にはcreateIndex()を使います。

引数にはフィールド名と昇順(=1)か降順(=-1)を指定します。

フィールド名はカンマ区切りで複数指定可能です。

[Mongoシェル]

1
2
3
4
5
6
> db.member.createIndex({LastName:1})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : false,
"ok" : 1

インデックスが1つから2つに増えたことが確認できます。

“ok”が1となっているのでインデックスが1つ作成されたということになります。


作成したインデックスを確認します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> db.member.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"LastName" : 1
},
"name" : "LastName_1"
}
]

デフォルトインデックス(_id)のほかに、LastNameフィールドにもインデックスが作成されていることが確認できます。

インデックス作成時にインデックス名を指定していなかったので、自動的に”LastName_1”というインデックス名になっています。


次回は、インデックス作成のオプションを確認します。

MongoDB(37) - インデックスの種類

MongoDBでは大量のデータを処理することが多いため、インデックスの作成は必須の設定と言えます。

今回はインデックスの種類についてまとめます。

インデックスの種類

MongoDBでは、次のようなインデックスの種類があります。

  • デフォルトインデックス
    _idフィールドに自動的に作成されるユニークなインデックスのことです。
    このデフォルトインデックスは削除することができません。
  • テキストインデックス
    文字列コンテンツに対するテキスト検索クエリーをサポートするインデックスのことです。
  • TTLインデックス
    特定の時間または特定の時刻に、自動的にドキュメントを削除することができるインデックスです。
  • ハッシュインデックス
    フィールド値のハッシュ値をインデックスします。
  • 地理的インデックス
    プレーンジオメトリを使用する2Dインデックスと、球面ジオメトリを使用する2Dsphereインデックスのことです。

インデックスをつけるべきフィールド

性能面の観点からインデックスをつけるべきフィールドは次の2つです。

  • 検索条件でよく使用するフィールド
  • コレクション結合のキーとなるフィールド

インデックスのデメリット

インデックスを作成すると検索を速くすることができますが、無駄なインデックスがあると次のようなデメリットが発生するので注意が必要です。

  1. 登録、更新、削除の処理が遅くなる。
  2. ディスクの使用量が多くなる。

ただ、このデメリット以上に検索がとても速くなるため、ほとんどのコレクションでインデックスを使うことになります。


次回は、インデックスの確認と作成を行います。

MongoDB(36) - 一括処理(Bulk)⑤一括削除

今回は、一括削除を行います。

一括削除処理(remove)

順次処理で一括削除を行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()の代わりにinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. removeクエリーを設定。(3~5行目)
  3. 一括実行(Bulk実行)。(7行目)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> var bulk = db.member.initializeOrderedBulkOp()

> bulk.find({LastName:'武元'}).removeOne()
> bulk.find({LastName:'松田'}).removeOne()
> bulk.find({LastName:'加藤'}).removeOne()

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 3,
"upserted" : [ ]
})

> db.member.find()
{ "_id" : ObjectId("613e8ff0d1340480894d324d"), "LastName" : "伊藤", "age" : 43 }

3件のドキュメントを一括で削除することができました。

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
from pymongo import DeleteOne
from pymongo.errors import BulkWriteError

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

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

# 一括入れ替え
requests = [
DeleteOne({'LastName': '武元'}),
DeleteOne({'LastName': '松田'}),
DeleteOne({'LastName': '加藤'})
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 入れ替え内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

次回からは、検索を高速化するためのインデックに関する操作を行います。

MongoDB(35) - 一括処理(Bulk)④一括登録/一括更新処理(upsert)

今回は、一括登録/一括更新処理(upsert)を行います。

一括登録/一括更新処理(upsert)

順次処理で一括登録/一括更新処理(upsert)を行います。

upsert処理では該当するデータが存在する場合は更新を行い、該当するデータがない場合は登録を行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()の代わりにinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. upsertクエリーを設定。(3~6行目)
    前半の3件が更新処理で、最後の1件が登録処理になります。
  3. 一括実行(Bulk実行)。(8行目)

[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
> var bulk = db.member.initializeOrderedBulkOp()

> bulk.find({LastName:'武元'}).upsert().updateOne({$set:{age:12}}) // 更新
> bulk.find({LastName:'松田'}).upsert().updateOne({$set:{age:23}}) // 更新
> bulk.find({LastName:'加藤'}).upsert().updateOne({$set:{age:33}}) // 更新
> bulk.find({LastName:'伊藤'}).upsert().updateOne({$set:{age:43}}) // 追加

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 1,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 0,
"upserted" : [
{
"index" : 3,
"_id" : ObjectId("613e8ff0d1340480894d324d")
}
]
})

> db.member.find()
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b87"), "LastName" : "武元", "FirstName" : "ゆい", "age" : 12 }
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b88"), "LastName" : "松田", "FirstName" : "りな", "age" : 23 }
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b89"), "LastName" : "加藤", "FirstName" : "しほ", "age" : 33 }
{ "_id" : ObjectId("613e8ff0d1340480894d324d"), "LastName" : "伊藤", "age" : 43 }

前半の3ドキュメントに関してはデータが存在していたので、既存データに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
import pymongo
from pymongo import MongoClient
from pymongo import UpdateOne
from pymongo.errors import BulkWriteError

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

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

# 一括入れ替え
requests = [
UpdateOne({'LastName': '武元'},{'$set':{'age':12}}, upsert=True),
UpdateOne({'LastName': '松田'},{'$set':{'age':23}}, upsert=True),
UpdateOne({'LastName': '加藤'},{'$set':{'age':33}}, upsert=True),
UpdateOne({'LastName': '伊藤'},{'$set':{'age':43}}, upsert=True)
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 入れ替え内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

Pythonでupsert処理を行う場合は、UpdateOneを使ってupsert=Trueオプションを追加します。


次回は、一括削除処理(remove)を行います。

MongoDB(34) - 一括処理(Bulk)③一括入れ替え

今回は、一括入れ替え処理を行います。

一括入れ替え

順次処理で一括入れ替えを行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()の代わりにinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. replaceクエリーを設定。(3~5行目)
  3. 一括実行(Bulk実行)。(7行目)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
> var bulk = db.member.initializeOrderedBulkOp()

> bulk.find({name:"武元"}).replaceOne({LastName:"武元", FirstName:"ゆい"})
> bulk.find({name:"松田"}).replaceOne({LastName:"松田", FirstName:"りな"})
> bulk.find({name:"加藤"}).replaceOne({LastName:"加藤", FirstName:"しほ"})

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 0,
"upserted" : [ ]
})
> db.member.find()
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b87"), "LastName" : "武元", "FirstName" : "ゆい" }
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b88"), "LastName" : "松田", "FirstName" : "りな" }
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b89"), "LastName" : "加藤", "FirstName" : "しほ" }

問題なく3つのドキュメントの入れ替えを行うことができました。

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
from pymongo import ReplaceOne
from pymongo.errors import BulkWriteError

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

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

# 一括入れ替え
requests = [
ReplaceOne({'name': '武元'},{'LastName':'武元', 'FirstName':'ゆい'}),
ReplaceOne({'name': '松田'},{'LastName':'松田', 'FirstName':'りな'}),
ReplaceOne({'name': '加藤'},{'LastName':'加藤', 'FirstName':'しほ'})
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 入れ替え内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

ReplaceOneの第1引数には検索条件を指定し、第2引数には入れ替えるドキュメントの内容を設定します。

次回は、一括登録/一括更新処理(upsert)を行います。

MongoDB(33) - 一括処理(Bulk)②一括更新

今回は、一括更新(Bulk)に関する操作を行います。

一括更新

順次処理で一括更新を行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()の代わりにinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. updateクエリーを設定。(3~5行目)
  3. 一括実行(Bulk実行)。(7行目)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> var bulk = db.member.initializeOrderedBulkOp()    //順次処理

> bulk.find({name:'武元'}).updateOne({$set:{age:11}})
> bulk.find({name:'松田'}).updateOne({$set:{age:21}})
> bulk.find({name:'加藤'}).updateOne({$set:{age:31}})

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 0,
"upserted" : [ ]
})

> db.member.find()
{ "_id" : ObjectId("613e8c820fb0f3e6cf9e2b81"), "name" : "武元", "age" : 11 }
{ "_id" : ObjectId("613e8c820fb0f3e6cf9e2b82"), "name" : "松田", "age" : 21 }
{ "_id" : ObjectId("613e8c820fb0f3e6cf9e2b83"), "name" : "加藤", "age" : 31 }

問題なく3つのドキュメントの年齢(age)を更新することができました。

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
from pymongo import UpdateOne
from pymongo.errors import BulkWriteError

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

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

# 一括更新
requests = [
UpdateOne({'name':'武元'}, {'$set':{'age':11}}),
UpdateOne({'name':'松田'}, {'$set':{'age':21}}),
UpdateOne({'name':'加藤'}, {'$set':{'age':31}})
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 更新内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

次回は、一括入れ替え処理を行います。


Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×