| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

「MongoDB」の版間の差分

提供: MyMemoWiki
ナビゲーションに移動 検索に移動
(ページの作成:「==MongoDB==」)
 
 
(同じ利用者による、間の146版が非表示)
1行目: 1行目:
 
==MongoDB==
 
==MongoDB==
 +
{{amazon|B07BGC4MJ1}}
 +
 +
[https://docs.mongodb.com/manual/ マニュアル]
 +
===ドキュメント指向データベース===
 +
----
 +
====スキーマレス====
 +
----
 +
*スキーマを定義しなくても利用できる
 +
*スキーマレスのため保守性が高い
 +
*JSON方式でデータを保持
 +
*テーブルのことはコレクションと呼ぶ
 +
====パフォーマンス====
 +
----
 +
*機能制限により、高パフォーマンスを実現
 +
*トランザクションがない
 +
**処理速度がかなり高速
 +
*大量データの高速処理に向く
 +
*スケールアウトが簡単な設定で可能
 +
====操作感====
 +
----
 +
*RDBと似た操作
 +
*複雑な検索条件を利用できる
 +
===インストール===
 +
----
 +
*https://docs.mongodb.com/manual/installation/
 +
====[[Ubuntu]]====
 +
----
 +
*[https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/ コミュニティエディション]
 +
 +
<pre>
 +
ubuntu@puli-mon:~$ cat /etc/os-release
 +
NAME="Ubuntu"
 +
VERSION="20.04.2 LTS (Focal Fossa)"
 +
  :
 +
ubuntu@puli-mon:~$ wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
 +
OK
 +
ubuntu@puli-mon:~$ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
 +
ubuntu@puli-mon:~$ sudo apt-get update
 +
ubuntu@puli-mon:~$ sudo apt-get install -y mongodb-org
 +
</pre>
 +
=====ディレクトリ=====
 +
----
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| 種類
 +
! scope="col"| 場所
 +
! scope="col"| 備考
 +
|-
 +
| データ
 +
| /var/lib/mongodb
 +
|
 +
|-
 +
| ログ
 +
| /var/log/mongodb
 +
|
 +
|-
 +
| 設定
 +
| /etc/mongod.conf
 +
|
 +
|-
 +
|}
 +
=====開始=====
 +
----
 +
<pre>
 +
ubuntu@puli-mon:/etc$ sudo systemctl start mongod
 +
</pre>
 +
*失敗する場合
 +
<pre>
 +
sudo systemctl daemon-reload
 +
</pre>
 +
=====リモートホストから接続=====
 +
----
 +
*デフォルトでは、localhostからのみ接続可能なため、bindIp の行を変更
 +
*$ sudo vi /etc/mongod.conf
 +
<pre>
 +
# network interfaces
 +
net:
 +
  port: 27017
 +
#  bindIp: 127.0.0.1
 +
  bindIp: 0.0.0.0
 +
</pre>
 +
===設定===
 +
----
 +
*/etc/momgod.conf
 +
*[http://docs.mongodb.org/manual/reference/configuration-options/ リファレンス]
 +
 +
 +
====systemlog====
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| パラメータ
 +
! scope="col"| 内容
 +
! scope="col"| 備考
 +
|-
 +
| destination
 +
| ログの送り先、fileまたはsyslogを指定
 +
|
 +
|-
 +
| path
 +
| ログを出力するファイル
 +
|
 +
|-
 +
| logAppend
 +
| trueの場合、ログを追記
 +
|
 +
|-
 +
| logRotage
 +
| ログローテーション。renameもしくはreopen
 +
|
 +
|-
 +
|}
 +
 +
====storage====
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| パラメータ
 +
! scope="col"| 内容
 +
! scope="col"| 備考
 +
|-
 +
 +
| dbPath
 +
| データファイル保存先
 +
|
 +
|-
 +
| journal enabled
 +
| ジャーナルを使用するかどうか
 +
|
 +
|-
 +
| engine
 +
| ストレージエンジンを指定
 +
|
 +
|-
 +
|
 +
*wiredTiger:
 +
**engineConfig:
 +
***cacheSizeGB:
 +
| 使用するメモリのキャッシュサイズ
 +
|
 +
|-
 +
|
 +
*wiredTiger:
 +
**collectionConfig:
 +
***blockCompressor:
 +
| 格納データを圧縮できる。圧縮率を指定できる
 +
*none:圧縮しない
 +
*snappy:圧縮する
 +
*zlib:snappyより高圧縮率で圧縮
 +
|
 +
|-
 +
|
 +
|
 +
|
 +
|-
 +
|
 +
|
 +
|
 +
|-
 +
|
 +
|
 +
|
 +
|-
 +
|
 +
|
 +
|
 +
|-
 +
|}
 +
 +
===monogoシェルの実行===
 +
----
 +
<pre>
 +
ubuntu@puli-mon:/etc$ mongo
 +
MongoDB shell version v4.4.6
 +
connecting to: mongodb://127.0.0.1:27017/?
 +
          :
 +
---
 +
>
 +
</pre>
 +
 +
==GUI==
 +
===[https://www.mongodb.com/products/compass MongaDB Compass]===
 +
----
 +
===[https://robomongo.org/ Robo 3T]===
 +
----
 +
*https://robomongo.org/download
 +
*Only 3T
 +
[[File:mongodb_gui_t3_download.png|500px]]
 +
*起動
 +
[[File:mongodb_gui_t3.png|500px]]
 +
 +
==データベース==
 +
===データベース作成===
 +
----
 +
*use で作成
 +
<pre>
 +
> use testdb
 +
switched to db testdb
 +
</pre>
 +
 +
*db。dろpDatabase() でカレントDBを削除
 +
 +
===コレクションを作成===
 +
----
 +
<pre>
 +
> db.createCollection("testDoc")
 +
{ "ok" : 1 }
 +
</pre>
 +
 +
*一覧を確認
 +
<pre>
 +
> show dbs
 +
admin  0.000GB
 +
config  0.000GB
 +
local  0.000GB
 +
testdb  0.000GB
 +
</pre>
 +
 +
===ドキュメントの登録===
 +
----
 +
*testDocは、コレクション
 +
<pre>
 +
> db.testDoc.insertOne(
 +
... {name:"Foo",value:"Bar"}
 +
... )
 +
{
 +
"acknowledged" : true,
 +
"insertedId" : ObjectId("609f57392efac2b731a534eb")
 +
}
 +
</pre>
 +
===検索===
 +
----
 +
*find
 +
<pre>
 +
> db.testDoc.find()
 +
{ "_id" : ObjectId("609f57392efac2b731a534eb"), "name" : "Foo", "value" : "Bar" }
 +
</pre>
 +
 +
===DB統計===
 +
----
 +
<pre>
 +
> db.stats()
 +
{
 +
"db" : "testdb",
 +
"collections" : 1,                      // コレクション数
 +
"views" : 0,   
 +
"objects" : 1,
 +
"avgObjSize" : 51,
 +
"dataSize" : 51,                      // 圧縮前データサイズ
 +
"storageSize" : 20480,
 +
"indexes" : 1,                          // インデックス数
 +
"indexSize" : 20480,            // インデックスデータ量
 +
"totalSize" : 40960,
 +
"scaleFactor" : 1,
 +
"fsUsedSize" : 2561937408,
 +
"fsTotalSize" : 20629221376,
 +
"ok" : 1
 +
}
 +
</pre>
 +
==コレクション==
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| 種類
 +
! scope="col"| コマンド
 +
! scope="col"| 例
 +
|-
 +
| コレクションの作成
 +
| db.createCollection(コレクション名)
 +
| db.createCollection("testCollection")
 +
|-
 +
| コレクションの一覧表示
 +
| show collections
 +
|
 +
|-
 +
| 統計情報表示
 +
| db.collection.stats()
 +
|
 +
|-
 +
| コレクションの削除
 +
| db.collection.drop()
 +
| db.testCollection.drop
 +
|-
 +
|}
 +
===Cappedコレクション===
 +
----
 +
*コレクションに入れられるデータの上限を設定
 +
*データ量が上限になると、古いドキュメントから削除されていく
 +
*レプリカセットでは、Cappedコレクションを使ってデータを同期している
 +
*createCollection のオプションを変更して作成
 +
<pre>
 +
db.createCollection(
 +
  "コレクション名",
 +
  [capped: true, size:  データ上限(バイト)サイズ]
 +
)
 +
</pre>
 +
==登録==
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| 方法
 +
! scope="col"| コマンド
 +
! scope="col"| 例
 +
|-
 +
| 1件登録
 +
| db.collection.insertOne({...})
 +
| db.testCollection.insertOne({key:"1",value:"a"})
 +
|-
 +
| 複数登録
 +
| db.collection.insertMany([
 +
{...},
 +
{...}
 +
])
 +
| db.testCollection.insertMany([
 +
{key:2,value:"b"},
 +
{key:3,value:"c"}
 +
])
 +
|}
 +
 +
==検索==
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| 方法
 +
! scope="col"| コマンド
 +
! scope="col"| 例
 +
|-
 +
| 全件
 +
| db.collection.find()
 +
| db.testCollection.find()
 +
|-
 +
| フィールドを指定
 +
| db.collection.find(
 +
{検索条件},
 +
{key1:0,kye2:1,...}
 +
)
 +
//key1を非表示、key2を表示
 +
|db.testCollection.find(
 +
{key:2},
 +
{_id:0,key:1,value:1}
 +
)
 +
|-
 +
| 完全一致
 +
| {key:value}
 +
|
 +
|-
 +
| 部分一致
 +
| {key:/value/}
 +
|
 +
|-
 +
| 前方一致
 +
| {key:/^value/}
 +
|
 +
|-
 +
| 後方一致
 +
| {key:/value$/}
 +
|
 +
|-
 +
| 以下
 +
| {key:{$lte:value}}
 +
|
 +
|-
 +
| 未満
 +
| {key:{$lt:value}}
 +
|
 +
|-
 +
| 以上
 +
| {key:{$gte:value}}
 +
|
 +
|-
 +
| より大きい
 +
| {key:{$gt:value}}
 +
|
 +
|-
 +
| 範囲指定
 +
| {key:{$gte:value1, $lte:value2}}
 +
|
 +
|-
 +
| and
 +
| {$and:[
 +
{key1:value1},
 +
{key2:value2}
 +
]}
 +
|
 +
|-
 +
| or
 +
| {$or:[
 +
{key1:value1},
 +
{key2:value2}
 +
]}
 +
|
 +
|-
 +
| null
 +
| {key:null}
 +
以下が検索される
 +
1.データ型がNull
 +
2.フィールドなし
 +
3.undefined
 +
|
 +
|-
 +
| フィールドの存在有無($exists)
 +
| { key: {$exists: false}}
 +
|
 +
|-
 +
| データ型を指定($type)
 +
| {key:{$type:"null"}}
 +
// Null型を指定して検索
 +
|
 +
|-
 +
| ソート
 +
| db.collection.find().sort({...})
 +
// 1:昇順,-1:降順
 +
| db.testCollection.find().sort(
 +
{key:-1}
 +
)
 +
|-
 +
| 件数
 +
| db.collection.find().count()
 +
|
 +
|-
 +
|}
 +
 +
==更新==
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| 方法
 +
! scope="col"| コマンド
 +
! scope="col"| 例
 +
|-
 +
| 1件ドキュメントを更新
 +
| db.collection.updateOne(
 +
{検索条件},
 +
{$set:{更新内容}}
 +
)
 +
| 一致するデータが複数あっても、1件しか更新されない
 +
db.testCollection.updateOne(
 +
{key:"1"}},
 +
{$set:{value2:"v2"}}
 +
)
 +
|-
 +
| 複数件のドキュメントを更新
 +
| db.collection.updateMany(
 +
{検索条件},
 +
{$set:{更新内容}}
 +
)
 +
| 更新に一致したドキュメントを全て更新
 +
db.testCollection.updateMany(
 +
{key:{$lt:4}},
 +
{$set:{value2:"v2"}}
 +
)
 +
|-
 +
| ドキュメントの置き換え
 +
| db.collection.replaceOne(
 +
{検索条件}
 +
{更新内容}
 +
)
 +
| 入れ替えられるのは1件だけ
 +
db.testCollection.replaceOne(
 +
{key:"1"},
 +
{key:1, value:"a", value2:"v1"}
 +
)
 +
|-
 +
| フィールド名を変更
 +
| $rename 旧Key:"新Key"
 +
| db.testCollection.updateMany(
 +
{},
 +
{$rename:{value:"val1"}}
 +
)
 +
|-
 +
| 配列のインデックス
 +
| フィールド名.n
 +
| {$set:{"ary.3":"hoge"}}
 +
|-
 +
| 登録または更新(upsert)
 +
| db.collection.updateOne(
 +
{検索条件},
 +
{更新内容},
 +
{upsert: true}
 +
)
 +
|
 +
|-
 +
|}
 +
===フィールドを新規追加===
 +
----
 +
*既存のフィールド($RaceId.Year ・・・)を接続して、新しいフィールド(_RaceId)を追加
 +
<pre>
 +
db.H1.update(
 +
    {"_id": ObjectId("60a7c66cb07a3cd94da9958c") },
 +
    [
 +
        {"$set": { "_RaceId": { $concat: [ "$RaceId.Year", "-", "$RaceId.MonthDay", "-","$RaceId.JyoCD", "-","$RaceId.Kaiji", "-","$RaceId.Nichiji", "-","$RaceId.RaceNum" ] } } }
 +
    ]
 +
)
 +
</pre>
 +
 +
==削除==
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| 方法
 +
! scope="col"| コマンド
 +
! scope="col"| 例
 +
|-
 +
| 1件削除
 +
| db.collection.deleteOne({検索条件})
 +
| 複数件一致しても、削除されるのは1件
 +
|-
 +
| 複数件削除
 +
| db.collection.deleteMany({検索条件})
 +
|
 +
|-
 +
|}
 +
==集計==
 +
*findで集計はできないため、aggregationメソッドを利用する
 +
*$group に 集計対象 _id は必須
 +
*全体の集計を行うときは、_id:null とする
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| 集計
 +
! scope="col"| 集計関数
 +
! scope="col"| 例
 +
|-
 +
| 最大値
 +
| $max
 +
|
 +
|-
 +
| 最小値
 +
| $min
 +
|
 +
|-
 +
| 平均値
 +
| $avg
 +
|
 +
|-
 +
|
 +
|
 +
|
 +
|-
 +
|}
 +
===簡単な集計===
 +
----
 +
<pre>
 +
db.collection.aggregate([
 +
  { $match:{<検索条件>}},
 +
  { $group:{ _id::"$<集計フィールド>",<集計結果表示名>:{<集計関数>:"$集計フィールド"}}}
 +
])
 +
</pre>
 +
====基本====
 +
**$group に 指定した _id フィールドごとに集計を行う
 +
**"$フィールド名"と入力する
 +
**集計関数 $sumを指定、複数指定も可能
 +
<pre>
 +
db.getCollection("O1").aggregate([
 +
    { $match: { 'head.MakeDate.Year':{ '$gt':'2010', '$lt':'2020' }} },
 +
    { $group: { _id:'$head.MakeDate.Year', tosu: {'$sum':{ '$toInt': '$TorokuTosu' }}} }
 +
])
 +
</pre>
 +
[[File:mongo_aggregate_sum.png|600px]]
 +
====グループ化のあとに、さらに条件を適用====
 +
<pre>
 +
db.getCollection("O1").aggregate([
 +
    { $match: { 'head.MakeDate.Year':{ '$gt':'2010', '$lt':'2020' }} },
 +
    { $group: { _id:'$head.MakeDate.Year', tosu: {'$sum':{ '$toInt': '$TorokuTosu' }}} },
 +
    { $match: { 'tosu' : { '$gt': 49000 }} }
 +
])
 +
</pre>
 +
[[File:mongo_aggregate_sum2.png|600px]]
 +
 +
====集計関数を複数同時に使用====
 +
<pre>
 +
db.getCollection("O1").aggregate([
 +
    { $match: { 'head.MakeDate.Year':{ '$gt':'2010', '$lt':'2020' }} },
 +
    { $group: { _id:'$head.MakeDate.Year',
 +
        tosu_total: {'$sum':{ '$toInt': '$TorokuTosu' }},
 +
        tosu_max: {'$max':{ '$toInt': '$TorokuTosu' }},
 +
        tosu_min: {'$min':{ '$toInt': '$TorokuTosu' }},
 +
        tosu_avg: {'$avg':{ '$toInt': '$TorokuTosu' }} }}
 +
])
 +
</pre>
 +
[[File:mongo_aggregate_sum3.png|600px]]
 +
====グループごとの件数をカウント====
 +
*$sum:1 とする
 +
<pre>
 +
db.getCollection("O1").aggregate([
 +
    { $match: { 'head.MakeDate.Year':{ '$gt':'2010', '$lt':'2020' }} },
 +
    { $group: { _id:'$head.MakeDate.Year',
 +
        tosu_total: {'$sum':{ '$toInt': '$TorokuTosu' }},
 +
        tosu_max: {'$max':{ '$toInt': '$TorokuTosu' }},
 +
        tosu_min: {'$min':{ '$toInt': '$TorokuTosu' }},
 +
        tosu_avg: {'$avg':{ '$toInt': '$TorokuTosu' }},
 +
        tosu_cnt: {'$sum':1} }}
 +
])
 +
</pre>
 +
===コレクションの結合===
 +
----
 +
*aggregationではコレクションを結合できる
 +
*$lookup を利用する
 +
<pre>
 +
db.collection.aggregate([
 +
  { $lookup:{
 +
    from: "<結合先コレクション>",
 +
    localField:"<結合元の結合フィールド>",
 +
    foreginField:"<結合先の結合フィールド>",
 +
    as:"<結合先コレクションの別名>"
 +
  }}
 +
])
 +
</pre>
 +
=====結合($lookup)=====
 +
<pre>
 +
db.RA.aggregate([
 +
  { $lookup:{
 +
    from:"SE",
 +
    localField:"_RaceId",
 +
    foreignField:"_RaceId",
 +
    as:"SE"
 +
  }}
 +
])
 +
</pre>
 +
=====検索条件を指定して結合($match)=====
 +
<pre>
 +
db.RA.aggregate([
 +
  { $match: { "_id" : ObjectId("60a7c617b07a3cd94da991b7") } }, // 検索条件
 +
  { $lookup:{
 +
    from:"SE",
 +
    localField:"_RaceId",
 +
    foreignField:"_RaceId",
 +
    as:"SE"
 +
  }}
 +
]) // 結合条件
 +
</pre>
 +
=====表示フィールドの絞り込み($project) =====
 +
<pre>
 +
db.RA.aggregate([
 +
  { $match: { "_id" : ObjectId("60a7c617b07a3cd94da991b7") } },
 +
  { $lookup:{
 +
    from:"SE",
 +
    localField:"_RaceId",
 +
    foreignField:"_RaceId",
 +
    as:"SE"
 +
  }},
 +
  { $project: {
 +
    "RaceInfo":1,
 +
    "JyokenInfo":1,
 +
    "SE":1
 +
  }}  // 表示フィールドの絞り込み
 +
]) 
 +
</pre>
 +
[[File:mongo_lookup.png|600px]]
 +
 +
===一括高速処理(Bulk)===
 +
----
 +
*Bulk操作には大きく2つのタイプ
 +
**順次処理:登録の順番に意味があるフィールドを持つ場合に使用
 +
**並列処理:順番に関係なく処理を実行
 +
====一括登録(insert)====
 +
----
 +
<pre>
 +
var bulk = db.collection.initializeOrderBulkOp(); //Bulkの実行タイプを指定
 +
bulk.insert({<登録ドキュメント>});
 +
bulk.execute(); // Bulkの実行
 +
</pre>
 +
====一括更新(update)====
 +
----
 +
<pre>
 +
var bulk = db.H6.initializeUnorderedBulkOp();
 +
bulk.find({}).update(
 +
  [{"$set": { "_RaceId": { $concat: [ "$RaceId.Year", "-", "$RaceId.MonthDay", "-","$RaceId.JyoCD", "-","$RaceId.Kaiji", "-","$RaceId.Nichiji", "-","$RaceId.RaceNum" ] } } }]
 +
);
 +
bulk.execute();
 +
</pre>
 +
 +
====一括登録または更新(upsert)====
 +
----
 +
====一括削除(remove)====
 +
----
 +
 +
==インデックス==
 +
===作成===
 +
----
 +
*1:昇順、-1:降順
 +
<pre>
 +
db.collection.createIndex(
 +
  { key1:1, key2:-1, ・・・},
 +
  { <インデックスオプション>}
 +
)
 +
</pre>
 +
====インデックスオプション====
 +
----
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| 項目
 +
! scope="col"| 説明
 +
! scope="col"| 備考
 +
|-
 +
| background
 +
| バックグラウンド実行
 +
| データ大量時、アプリケーションへの応答遅延防止など
 +
|-
 +
| name
 +
| インデックス名を指定
 +
|
 +
|-
 +
| unique
 +
| ユニークインデックス
 +
| null不可
 +
|-
 +
| partialFilterExpression
 +
| フィルタを作成し一致したドキュメントの部分インデックスを作成
 +
| 以下を指定できる
 +
*等式(key: value , $eq)
 +
*$exists
 +
*$gt, $gte, $lt, $lte
 +
*$type ・$and
 +
|-
 +
|}
 +
====インデックス種類====
 +
----
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| 種類
 +
! scope="col"| 説明
 +
! scope="col"| 備考
 +
|-
 +
| デフォルトインデックス
 +
| _idフィールドに作成される
 +
| 削除できない
 +
|-
 +
| テキストインデックス
 +
| 文字列コンテンツに対するテキスト検索クエリをサポートするテキストインデックスを作成
 +
| 作成には、keyに"text"を指定する
 +
<pre>
 +
db.collection.createIndex({ key: "text" })
 +
</pre>
 +
|-
 +
| TTLインデックス
 +
| 特定の時間または時刻にドキュメントを自動削除するために利用する
 +
| Date型、Date型を含む配列、expireAfterSecondsが経過したドキュメントを自動で削除する
 +
<pre>
 +
db.collection.createIndex({
 +
  {key: 1},
 +
  {expireAfterSeconds:<秒数>}
 +
})
 +
</pre>
 +
|-
 +
| ハッシュインデックス
 +
| フィールド値のハッシュをインデックスにする
 +
| ランダム分布をも持つが、値一致飲みサポート
 +
|-
 +
|地理的インデックス
 +
|プレーンジオメトリ、球面ジオメトリ
 +
|
 +
|}
 +
 +
===確認===
 +
----
 +
<pre>
 +
db.collection.getIndexes()
 +
</pre>
 +
===削除===
 +
----
 +
*上記で確認した、nameを指定する
 +
<pre>
 +
db.collection.dropIndex("インデックス名")
 +
</pre>
 +
===再構築===
 +
----
 +
<pre>
 +
db.collection.reIndex()
 +
</pre>
 +
 +
==Tips==
 +
===stringをintに変換===
 +
<pre>
 +
db.getCollection('O1').find({},{tosu:{ '$toInt': '$TorokuTosu' }})
 +
</pre>
 +
[[File:mongo_to_into.png|500px]]
 +
 +
==プログラミング==
 +
===[[C Sharp|C#]]===
 +
----
 +
*[https://mongodb.github.io/mongo-csharp-driver/2.8/apidocs/html/R_Project_CSharpDriverDocs.htm C# MongoDriver]
 +
====Insert====
 +
----
 +
<pre>
 +
using MongoDB.Driver;
 +
  :
 +
var client = new MongoClient("mongodb://puli-mon.local");
 +
var mongoDb = client.GetDatabase("jra");
 +
var colH1 = mongoDb.GetCollection<JV_H1_HYOSU_ZENKAKE>("h1");
 +
  :
 +
colH1.InsertOne(rec);
 +
</pre>

2021年6月16日 (水) 00:04時点における最新版

MongoDB

マニュアル

ドキュメント指向データベース


スキーマレス


  • スキーマを定義しなくても利用できる
  • スキーマレスのため保守性が高い
  • JSON方式でデータを保持
  • テーブルのことはコレクションと呼ぶ

パフォーマンス


  • 機能制限により、高パフォーマンスを実現
  • トランザクションがない
    • 処理速度がかなり高速
  • 大量データの高速処理に向く
  • スケールアウトが簡単な設定で可能

操作感


  • RDBと似た操作
  • 複雑な検索条件を利用できる

インストール


Ubuntu


ubuntu@puli-mon:~$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
   :
ubuntu@puli-mon:~$ wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
OK
ubuntu@puli-mon:~$ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
ubuntu@puli-mon:~$ sudo apt-get update
ubuntu@puli-mon:~$ sudo apt-get install -y mongodb-org
ディレクトリ

種類 場所 備考
データ /var/lib/mongodb
ログ /var/log/mongodb
設定 /etc/mongod.conf
開始

ubuntu@puli-mon:/etc$ sudo systemctl start mongod
  • 失敗する場合
sudo systemctl daemon-reload
リモートホストから接続

  • デフォルトでは、localhostからのみ接続可能なため、bindIp の行を変更
  • $ sudo vi /etc/mongod.conf
# network interfaces
net:
  port: 27017
#  bindIp: 127.0.0.1
  bindIp: 0.0.0.0

設定



systemlog

パラメータ 内容 備考
destination ログの送り先、fileまたはsyslogを指定
path ログを出力するファイル
logAppend trueの場合、ログを追記
logRotage ログローテーション。renameもしくはreopen

storage

パラメータ 内容 備考
dbPath データファイル保存先
journal enabled ジャーナルを使用するかどうか
engine ストレージエンジンを指定
  • wiredTiger:
    • engineConfig:
      • cacheSizeGB:
使用するメモリのキャッシュサイズ
  • wiredTiger:
    • collectionConfig:
      • blockCompressor:
格納データを圧縮できる。圧縮率を指定できる
  • none:圧縮しない
  • snappy:圧縮する
  • zlib:snappyより高圧縮率で圧縮

monogoシェルの実行


ubuntu@puli-mon:/etc$ mongo
MongoDB shell version v4.4.6
connecting to: mongodb://127.0.0.1:27017/?
          :
---
> 

GUI

MongaDB Compass


Robo 3T


Mongodb gui t3 download.png

  • 起動

Mongodb gui t3.png

データベース

データベース作成


  • use で作成
> use testdb
switched to db testdb
  • db。dろpDatabase() でカレントDBを削除

コレクションを作成


> db.createCollection("testDoc")
{ "ok" : 1 }
  • 一覧を確認
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
testdb  0.000GB

ドキュメントの登録


  • testDocは、コレクション
> db.testDoc.insertOne(
... {name:"Foo",value:"Bar"}
... )
{
	"acknowledged" : true,
	"insertedId" : ObjectId("609f57392efac2b731a534eb")
}

検索


  • find
> db.testDoc.find()
{ "_id" : ObjectId("609f57392efac2b731a534eb"), "name" : "Foo", "value" : "Bar" }

DB統計


> db.stats()
{
	"db" : "testdb",
	"collections" : 1,                       // コレクション数
	"views" : 0,    
	"objects" : 1,
	"avgObjSize" : 51,
	"dataSize" : 51,                       // 圧縮前データサイズ
	"storageSize" : 20480,
	"indexes" : 1,                           // インデックス数
	"indexSize" : 20480,             // インデックスデータ量
	"totalSize" : 40960,
	"scaleFactor" : 1,
	"fsUsedSize" : 2561937408,
	"fsTotalSize" : 20629221376,
	"ok" : 1
}

コレクション

種類 コマンド
コレクションの作成 db.createCollection(コレクション名) db.createCollection("testCollection")
コレクションの一覧表示 show collections
統計情報表示 db.collection.stats()
コレクションの削除 db.collection.drop() db.testCollection.drop

Cappedコレクション


  • コレクションに入れられるデータの上限を設定
  • データ量が上限になると、古いドキュメントから削除されていく
  • レプリカセットでは、Cappedコレクションを使ってデータを同期している
  • createCollection のオプションを変更して作成
db.createCollection(
  "コレクション名",
  [capped: true, size:  データ上限(バイト)サイズ]
)

登録

方法 コマンド
1件登録 db.collection.insertOne({...}) db.testCollection.insertOne({key:"1",value:"a"})
複数登録 db.collection.insertMany([

{...}, {...} ])

db.testCollection.insertMany([

{key:2,value:"b"}, {key:3,value:"c"} ])

検索

方法 コマンド
全件 db.collection.find() db.testCollection.find()
フィールドを指定 db.collection.find(

{検索条件}, {key1:0,kye2:1,...} ) //key1を非表示、key2を表示

db.testCollection.find(

{key:2}, {_id:0,key:1,value:1} )

完全一致 {key:value}
部分一致 {key:/value/}
前方一致 {key:/^value/}
後方一致 {key:/value$/}
以下 {key:{$lte:value}}
未満 {key:{$lt:value}}
以上 {key:{$gte:value}}
より大きい {key:{$gt:value}}
範囲指定 {key:{$gte:value1, $lte:value2}}
and {$and:[

{key1:value1}, {key2:value2} ]}

or {$or:[

{key1:value1}, {key2:value2} ]}

null {key:null}

以下が検索される 1.データ型がNull 2.フィールドなし 3.undefined

フィールドの存在有無($exists) { key: {$exists: false}}
 データ型を指定($type) {key:{$type:"null"}}

// Null型を指定して検索

ソート db.collection.find().sort({...})

// 1:昇順,-1:降順

db.testCollection.find().sort(

{key:-1} )

件数 db.collection.find().count()

更新

方法 コマンド
1件ドキュメントを更新 db.collection.updateOne(

{検索条件}, {$set:{更新内容}} )

一致するデータが複数あっても、1件しか更新されない

db.testCollection.updateOne( {key:"1"}}, {$set:{value2:"v2"}} )

複数件のドキュメントを更新 db.collection.updateMany(

{検索条件}, {$set:{更新内容}} )

更新に一致したドキュメントを全て更新

db.testCollection.updateMany( {key:{$lt:4}}, {$set:{value2:"v2"}} )

ドキュメントの置き換え db.collection.replaceOne(

{検索条件} {更新内容} )

入れ替えられるのは1件だけ

db.testCollection.replaceOne( {key:"1"}, {key:1, value:"a", value2:"v1"} )

フィールド名を変更 $rename 旧Key:"新Key" db.testCollection.updateMany(

{}, {$rename:{value:"val1"}} )

配列のインデックス フィールド名.n {$set:{"ary.3":"hoge"}}
登録または更新(upsert) db.collection.updateOne(

{検索条件}, {更新内容}, {upsert: true} )

フィールドを新規追加


  • 既存のフィールド($RaceId.Year ・・・)を接続して、新しいフィールド(_RaceId)を追加
db.H1.update(
    {"_id": ObjectId("60a7c66cb07a3cd94da9958c") },
    [ 
        {"$set": { "_RaceId": { $concat: [ "$RaceId.Year", "-", "$RaceId.MonthDay", "-","$RaceId.JyoCD", "-","$RaceId.Kaiji", "-","$RaceId.Nichiji", "-","$RaceId.RaceNum" ] } } }
    ]
 )

削除

方法 コマンド
1件削除 db.collection.deleteOne({検索条件}) 複数件一致しても、削除されるのは1件
複数件削除 db.collection.deleteMany({検索条件})

集計

  • findで集計はできないため、aggregationメソッドを利用する
  • $group に 集計対象 _id は必須
  • 全体の集計を行うときは、_id:null とする
集計 集計関数
最大値 $max
最小値 $min
平均値 $avg

簡単な集計


db.collection.aggregate([
  { $match:{<検索条件>}},
  { $group:{ _id::"$<集計フィールド>",<集計結果表示名>:{<集計関数>:"$集計フィールド"}}}
])

基本

    • $group に 指定した _id フィールドごとに集計を行う
    • "$フィールド名"と入力する
    • 集計関数 $sumを指定、複数指定も可能
db.getCollection("O1").aggregate([
    { $match: { 'head.MakeDate.Year':{ '$gt':'2010', '$lt':'2020' }} },
    { $group: { _id:'$head.MakeDate.Year', tosu: {'$sum':{ '$toInt': '$TorokuTosu' }}} }
])

Mongo aggregate sum.png

グループ化のあとに、さらに条件を適用

db.getCollection("O1").aggregate([
    { $match: { 'head.MakeDate.Year':{ '$gt':'2010', '$lt':'2020' }} },
    { $group: { _id:'$head.MakeDate.Year', tosu: {'$sum':{ '$toInt': '$TorokuTosu' }}} },
    { $match: { 'tosu' : { '$gt': 49000 }} } 
])

Mongo aggregate sum2.png

集計関数を複数同時に使用

db.getCollection("O1").aggregate([
    { $match: { 'head.MakeDate.Year':{ '$gt':'2010', '$lt':'2020' }} },
    { $group: { _id:'$head.MakeDate.Year', 
        tosu_total: {'$sum':{ '$toInt': '$TorokuTosu' }},
        tosu_max: {'$max':{ '$toInt': '$TorokuTosu' }},
        tosu_min: {'$min':{ '$toInt': '$TorokuTosu' }},
        tosu_avg: {'$avg':{ '$toInt': '$TorokuTosu' }} }}
])

Mongo aggregate sum3.png

グループごとの件数をカウント

  • $sum:1 とする
db.getCollection("O1").aggregate([
    { $match: { 'head.MakeDate.Year':{ '$gt':'2010', '$lt':'2020' }} },
    { $group: { _id:'$head.MakeDate.Year', 
        tosu_total: {'$sum':{ '$toInt': '$TorokuTosu' }},
        tosu_max: {'$max':{ '$toInt': '$TorokuTosu' }},
        tosu_min: {'$min':{ '$toInt': '$TorokuTosu' }},
        tosu_avg: {'$avg':{ '$toInt': '$TorokuTosu' }},
        tosu_cnt: {'$sum':1} }}
])

コレクションの結合


  • aggregationではコレクションを結合できる
  • $lookup を利用する
db.collection.aggregate([
  { $lookup:{
     from: "<結合先コレクション>",
     localField:"<結合元の結合フィールド>",
     foreginField:"<結合先の結合フィールド>",
     as:"<結合先コレクションの別名>"
  }}
])
結合($lookup)
db.RA.aggregate([
  { $lookup:{
     from:"SE",
     localField:"_RaceId",
     foreignField:"_RaceId",
     as:"SE" 
  }}
])
検索条件を指定して結合($match)
db.RA.aggregate([
  { $match: { "_id" : ObjectId("60a7c617b07a3cd94da991b7") } }, // 検索条件
  { $lookup:{
     from:"SE",
     localField:"_RaceId",
     foreignField:"_RaceId",
     as:"SE" 
  }}
]) // 結合条件
表示フィールドの絞り込み($project)
db.RA.aggregate([
  { $match: { "_id" : ObjectId("60a7c617b07a3cd94da991b7") } },
  { $lookup:{
     from:"SE",
     localField:"_RaceId",
     foreignField:"_RaceId",
     as:"SE" 
  }},
  { $project: {
     "RaceInfo":1,
     "JyokenInfo":1,
     "SE":1
  }}  // 表示フィールドの絞り込み
]) 

Mongo lookup.png

一括高速処理(Bulk)


  • Bulk操作には大きく2つのタイプ
    • 順次処理:登録の順番に意味があるフィールドを持つ場合に使用
    • 並列処理:順番に関係なく処理を実行

一括登録(insert)


var bulk = db.collection.initializeOrderBulkOp(); //Bulkの実行タイプを指定
bulk.insert({<登録ドキュメント>});
bulk.execute(); // Bulkの実行

一括更新(update)


var bulk = db.H6.initializeUnorderedBulkOp();
bulk.find({}).update(
  [{"$set": { "_RaceId": { $concat: [ "$RaceId.Year", "-", "$RaceId.MonthDay", "-","$RaceId.JyoCD", "-","$RaceId.Kaiji", "-","$RaceId.Nichiji", "-","$RaceId.RaceNum" ] } } }]
);
bulk.execute();

一括登録または更新(upsert)


一括削除(remove)


インデックス

作成


  • 1:昇順、-1:降順
db.collection.createIndex(
  { key1:1, key2:-1, ・・・},
  { <インデックスオプション>}
)

インデックスオプション


項目 説明 備考
background バックグラウンド実行 データ大量時、アプリケーションへの応答遅延防止など
name インデックス名を指定
unique ユニークインデックス null不可
partialFilterExpression フィルタを作成し一致したドキュメントの部分インデックスを作成 以下を指定できる
  • 等式(key: value , $eq)
  • $exists
  • $gt, $gte, $lt, $lte
  • $type ・$and

インデックス種類


種類 説明 備考
デフォルトインデックス _idフィールドに作成される 削除できない
テキストインデックス 文字列コンテンツに対するテキスト検索クエリをサポートするテキストインデックスを作成 作成には、keyに"text"を指定する
db.collection.createIndex({ key: "text" })
TTLインデックス 特定の時間または時刻にドキュメントを自動削除するために利用する Date型、Date型を含む配列、expireAfterSecondsが経過したドキュメントを自動で削除する
db.collection.createIndex({
  {key: 1},
  {expireAfterSeconds:<秒数>}
})
ハッシュインデックス フィールド値のハッシュをインデックスにする ランダム分布をも持つが、値一致飲みサポート
地理的インデックス プレーンジオメトリ、球面ジオメトリ

確認


db.collection.getIndexes()

削除


  • 上記で確認した、nameを指定する
db.collection.dropIndex("インデックス名")

再構築


db.collection.reIndex()

Tips

stringをintに変換

db.getCollection('O1').find({},{tosu:{ '$toInt': '$TorokuTosu' }})

Mongo to into.png

プログラミング

C#


Insert


using MongoDB.Driver;
   :
var client = new MongoClient("mongodb://puli-mon.local");
var mongoDb = client.GetDatabase("jra");
var colH1 = mongoDb.GetCollection<JV_H1_HYOSU_ZENKAKE>("h1");
   :
colH1.InsertOne(rec);