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

MyMemoWiki

MongoDB

提供: MyMemoWiki
2021年6月11日 (金) 23:49時点におけるPiroto (トーク | 投稿記録)による版 (→‎インデックスオプション)
ナビゲーションに移動 検索に移動

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

monogoシェルの実行


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

GUI

データベース

データベース作成


  • 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' }}} }
])

 

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

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 }} } 
])

 

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

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' }} }}
])

 

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

  • $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
  }}  // 表示フィールドの絞り込み
]) 

 

一括高速処理(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

Tips

stringをintに変換

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

 

プログラミング

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);