Mongo shellの操作まとめ
下記の環境で動作確認を行いました。
- Windows7 (64bit)
- MongoDB 3.0.2
この記事の説明で使用するコレクション
- データベース:
test
- コレクション名:
product
Field | Data Type | Desc |
---|---|---|
no | no | 品番 |
name | string | 品名 |
price | int | 価格 |
variety | array | (*)バラエティ |
snack | boolean | 食用油で揚げている菓子類 |
drink | boolean | 清涼飲料水類 |
activate | boolean | true:取扱可、false:不可 |
update_dt | date | 更新日 |
バラエティ配列の要素は下記のオブジェクト
Field | Data Type | Desc |
---|---|---|
flavor | string | 味 |
ppl | int | 人気度(3:大、2:中、1:小) |
サンプルデータの準備
この後の説明で使用するデータを下記のように作成します。
> use test
> db.product.insert([
{no:1, name:"うまい棒", price:10, variety:[{flavor:"メンタイ", ppl:3},{flavor:"サラミ", ppl:3},{flavor:"ピザ", ppl:2},{flavor:"オニオンサラダ", ppl:2},{flavor:"コーンポタージュ", ppl:1}], snack:true, activate:true, update_dt:ISODate("2015-01-01T00:00:00+09:00") },
{no:2, name:"ポテトフライ", price:30, variety:[{flavor:"ステーキ", ppl:2},{flavor:"フライドチキン", ppl:1},{flavor:"カルビ", ppl:2}], snack:true, activate:false, update_dt:ISODate("2015-01-15T00:00:00+09:00") },
{no:3, name:"きなこ棒", price:10, activate:true, update_dt:ISODate("2015-01-31T00:00:00+09:00")},
{no:4, name:"生いきビール", price:40, drink:true, activate:false, update_dt:ISODate("2015-02-01T00:00:00+09:00")},
{no:5, name:"フルーツヨーグル", price:20, activate:true, update_dt:ISODate("2015-02-15T00:00:00+09:00")},
{no:6, name:"コーヒー牛乳キャンディ", price:10, activate:true, update_dt:ISODate("2015-02-28T00:00:00+09:00")},
{no:7, name:"ミニコーラ", price:30, activate:true, update_dt:ISODate("2015-03-01T00:00:00+09:00")},
{no:8, name:"フエラムネ", price:60, variety:[{flavor:"コーラ", ppl:3},{flavor:"いちご", ppl:1}], activate:true, update_dt:ISODate("2015-03-15T00:00:00+09:00")},
{no:9, name:"こざくら餅", price:20, variety:[{flavor:"グレープ", ppl:2},{flavor:"コーラ", ppl:3},{flavor:"フルーツソーダ", ppl:1},{flavor:"ミックス", ppl:2}], activate:true, update_dt:ISODate("2015-03-31T00:00:00+09:00")},
{no:10,name:"たまごアイス", price:10, variety:[{flavor:"ミルク", ppl:1},{flavor:"バニラ", ppl:3},{flavor:"チョコレート", ppl:2}], activate:true, update_dt:ISODate("2015-04-01T00:00:00+09:00")},
{no:11,name:"餅太郎", price:30, activate:true, update_dt:ISODate("2015-04-15T00:00:00+09:00")},
{no:12,name:"あんこ玉", price:10, activate:true, update_dt:ISODate("2015-04-30T00:00:00+09:00")},
{no:13,name:"ラムネ", price:30, drink:true, activate:true, update_dt:ISODate("2015-05-01T00:00:00+09:00")},
{no:14,name:"みかん水", price:40, drink:true, activate:true, update_dt:ISODate("2015-05-15T00:00:00+09:00")},
{no:15,name:"さくら大根", activate:false, update_dt:ISODate("2015-05-15T00:00:00+09:00"), desc:"価格不明"}
])
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 15,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
collection
createCollection()
db.createCollection(name, options)
コレクションの作成はcreateCollection()
を使用して明示的に作成する方法とinsert()
で暗黙的に作成する方法があります。
コレクション名を指定してコレクションを作成します。
> db.createCollection("product")
{ "ok" : 1 }
insert時にコレクションが存在しなければ暗黙的に作成します。
> db.product.insert({...})
コレクション作成時に指定するオプションでCapped collectionを作成することができます。
この例ではコレクションサイズの上限を1GB、ドキュメント数を100万件に指定しています。
> db.createCollection("product", {capped:true, size:1073741824, max:1000000})
{ "ok" : 1 }
options (一部)
Field | Type | Description |
---|---|---|
capped | Boolean | Optional. true/false. trueにした場合sizeの指定も 必要. |
autoIndexId | Boolean | Optional. true/false. falseにした場合_idインデックスは作成されません。 |
size | Number | Optional. コレクションの最大byte数. 最小4KBで256の整数倍で指定. |
max | Number | Optional. コレクションの最大ドキュメント数. max値を超えてドキュメントを登録すると古いドキュメントから削除される. |
capped collectionはremove()でドキュメントを削除することはできません。
> db.product.remove({_id:ObjectId("55537369d5ce22def8f104e1")})
WriteResult({
"nRemoved" : 0,
"writeError" : {
"code" : 20,
"errmsg" : "cannot remove from a capped collection: test.product"
}
})
MongoDB Reference - db.createCollection
MongoDB Manual - Capped Collections
stats()
db.collection.stats(options)
コレクションの状態はstats()
で確認できます。(下記はサンプルデータ登録後の状態です。)
> db.product.stats()
{
"ns" : "test.product",
"count" : 15,
"size" : 3856,
"avgObjSize" : 257,
"numExtents" : 1,
"storageSize" : 8192,
"lastExtentSize" : 8192,
"paddingFactor" : 1,
"paddingFactorNote" : "paddingFactor is unused and unmaintained in 3.0.
It remains hard coded to 1.0 for compatibility only.",
"userFlags" : 1,
"capped" : false,
"nindexes" : 1,
"totalIndexSize" : 8176,
"indexSizes" : {
"_id_" : 8176
},
"ok" : 1
}
Field | Description |
---|---|
ns | namespace |
count | number of documents |
size | collection size in bytes |
avgObjSize | average object size in bytes |
numExtents | The total number of contiguously allocated data file regions. |
storageSize | (pre)allocated space for the collection in bytes |
lastExtentSize | The size of the last extent allocated. |
paddingFactor | Deprecated since version 3.0.0 |
paddingFactorNote | |
userFlags | A number that indicates the user-set flags on the collection. |
capped | This field will be “true” if the collection is capped. |
max | Shows the maximum number of documents that may be present in a capped collection. |
maxSize | Shows the maximum size of a capped collection. |
nindexes | number of indexes |
totalIndexSize | total index size in bytes |
indexSizes | size of specific indexes in bytes |
オプションでscaleを1024に設定するとデータサイズがKB単位で表示されます。
> db.product.stats({scale:1024})
その他にも下記の状態確認用メソッドがあります。
> db.product.isCapped()
false
> db.product.dataSize()
3856
> db.product.storageSize()
8192
> db.product.totalSize()
16368
> db.product.totalIndexSize()
8176
find()
db.collection.find(<query>)
db.collection.find(<query>, <projection>)
コレクションからドキュメントを検索します。
無条件で検索する
> db.product.find()
または{}
を明示的に渡すことでも無条件の検索になります。
> db.product.find( {} )
条件を指定して検索する
検索条件をfind()
の第1引数(query)に記述します。
この例では_id
を指定して検索します。
> db.product.find(
{_id: ObjectId("5553d954e8b70b81d56a0383")}
)
nameフィールドが"うまい棒"と等価なドキュメントを検索します。
> db.product.find( {name:"うまい棒"} )
priceフィールドが10と等価なドキュメントを検索します。
> db.product.find( {price:10} )
ただし、次のような比較演算子を使った検索は行えません。
このような検索は後述するQuery Selectorsを使用します。
> db.product.find( {price: >= 10} )
2015-05-17T07:21:21.726+0900 E QUERY SyntaxError: Unexpected token >=
配列要素に対して検索する
フィールドに配列を記述することで配列要素に対する検索が行えます。
> db.product.find( {"variety.flavor":"コーラ"} )
添え字を指定して検索することができます。
この例ではvariety[0].flavorが"コーラ"のドキュメントを検索します。
> db.product.find( {"variety.0.flavor":"コーラ"} )
Query Selectors
$eq
,$gte
,$exists
などをQuery Selectorといいます。
Comparison Query Operators
$eq
, &ne
, $gt
, $gte
, $lt
, $lte
, $in
, $nin
$eq
$eq
を使用したnameフィールドが"うまい棒"の検索です。
> db.product.find( {name: {$eq:"うまい棒"}} )
$gte
priceフィールドが50以上のドキュメントを検索します。
> db.product.find( {price: {$gte:50}} )
$lte
priceフィールドが30以下のドキュメントを検索します。
> db.product.find( {price: {$lte:30}} )
priceフィールドが20以上かつ40以下のドキュメントを検索します。
> db.product.find( {price: {$gte:20, $lte:40}} )
$in
{ field: { $in: [ <value1>, <value2>, ... <valueN> ] } }
priceフィールドが20か40のドキュメントを検索します。
> db.product.find( {price: {$in:[20,40]}} )
$nin
{ field: { $nin: [ <value1>, <value2> ... <valueN> ] } }
priceフィールドが30および50以外のドキュメントを検索します。
なお、この例のようにpriceフィールドが存在しないドキュメントも検索されます。
> db.product.find( {price: {$nin:[30,50]}} )
priceフィールドが存在しないドキュメントを除外したい場合は$exists
も使用します。
> db.product.find(
{$and:[ {price: { $nin:[30,50] }},
{price: { $exists:true} } ]}
)
Logical Query Operators
$or
, $and
, $not
, $nor
$or
{ $or: [ {<expression1>}, {<expression2>}, ... , {<expressionN>} ] }
update_dtフィールドが4/30か5/01のドキュメントを検索します。
> db.product.find(
{$or:[ {update_dt:{$eq:ISODate("2015-04-30T00:00:00+09:00")}},
{update_dt:{$eq:ISODate("2015-05-01T00:00:00+09:00")}} ]}
)
$and
{ $and: [ {<expression1>}, {<expression2>} , ... , {<expressionN>} ] }
priceフィールドが10で且つupdate_dtフィールドが1/31のドキュメントを検索します。
> db.product.find(
{$and:[ {price:{$eq:10}},
{update_dt:{$eq:ISODate("2015-01-31T00:00:00+09:00")}} ]}
)
$not
{ field: { $not: {<operator-expression>} } }
priceフィールドが10ではないドキュメントを検索します。
$nin
と同様にpriceフィールドが存在しないドキュメントも検索されます。
> db.product.find( {price: { $not: {$eq:10} }} )
priceフィールドが存在しないドキュメントを除外したい場合は$exists
も使用します。
> db.product.find(
{$and:[ {price: { $not:{$eq:10} }},
{price: { $exists:true} } ]}
)
$nor
与えられた式をすべて満たさないドキュメントを検索します。
{ $nor: [ {<expression1>}, {<expression2>}, ... {<expressionN>} ] }
この例ではこれらの条件を満たすドキュメントを検索します。
- priceフィールドが30では無く且つdrinkフィールドがtrueでは無い
- priceフィールドが30では無く且つdrinkフィールドが存在しない
- priceフィールドが存在しなく且つdrinkフィールドがtrueでは無い
- priceフィールドもdrinkフィールドも存在しない
> db.product.find(
{$nor: [{price:30},
{drink:true}]}
)
Element Query Operators
$exists
, $type
$exists
{ field: { $exists: <boolean> } }
drinkフィールドが存在するドキュメントを検索します。
> db.product.find( {drink: {$exists:true}} )
$type
{ field: { $type: <BSON type> } }
update_dtフィールドがdate型(9)のドキュメントを検索します。
> db.product.find( {update_dt:{$type:9}} )
Available Types
Type | Number | Notes |
---|---|---|
Double | 1 | |
String | 2 | |
Object | 3 | |
Array | 4 | |
Binary data | 5 | |
Undefined | 6 | Deprecated. |
Object id | 7 | |
Boolean | 8 | |
Date | 9 | |
Null | 10 | |
Regular Expression | 11 | |
JavaScript | 13 | |
Symbol | 14 | |
JavaScript (with scope) | 15 | |
32-bit integer | 16 | |
Timestamp | 17 | |
64-bit integer | 18 | |
Min key | 255 | Query with -1. |
Max key | 127 |
Evaluation Query Operators
$mod
, $regex
, $text
, $where
$mod
剰余が指定した値と同じドキュメントを検索します。
{ field: { $mod: [ divisor, remainder ] } }
noフィールドが5の整数倍のドキュメントを検索します。
> db.product.find( {no: {$mod:[5, 0]} } )
$regex
検索条件に正規表現を使用します。
{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }
$text
全文検索を行います。そのためにはtext indexを作成する必要があります。(現時点では日本語は未対応の模様)
{ $text: { $search: <string>, $language: <string> } }
[MongoDB reference - Text search Languages] (http://docs.mongodb.org/manual/reference/text-search-languages/)
$where
条件にjavascirptを使用します。
{ $where: "javascript" }
priceフィールドが10以上20以下のドキュメントを検索します。
> db.product.find(
{$where:"this.price >= 10 && this.price <= 20"}
)
Array Query Operators
$all
,$elemMatch
,$size
$all
指定された要素をすべて含む配列を持つドキュメントを検索します。
{ <field>: { $all: [ <value1> , <value2> ... ] } }
> db.product.find(
{"variety.flavor": { $all: ["コーラ", "グレープ"] } }
)
$all
を使用しなくても同様の検索を行えます。
> db.product.find(
{$and: [ {"variety.flavor":"コーラ"},
{"variety.flavor":"グレープ"} ] }
)
$elemMatch
条件を満たす配列を持つドキュメントを検索します。
{ <field>: { $elemMatch: { <query1>, <query2>, ... } } }
> db.product.find(
{variety:{ $elemMatch:{ flavor:{$eq:"コーラ"}, ppl:{$gte:3} } }}
)
$elemMatch
を使用しなくても同様の検索を行えます。
> db.product.find(
{$and:[ {"variety.flavor":{$eq:"コーラ"}},
{"variety.ppl":{$gte:3}}]}
)
$size
指定する要素数の配列を持つドキュメントを検索します。
{ <field>: { $size: <number> } }
> db.product.find(
{variety:{ $size:3 }}
)
取得するフィールドを選択する
取得するフィールドをfind()
の第2引数(projection)に記述します。フィールド名とフラグ(1:取得、0:除外)を指定します。(_id
は指定しなくても含まれるようです。)
> db.product.find({}, {name:1, price:1})
フィールドに0を指定すると除外することができます。この例では_id
を除外しています。
> db.product.find({}, {_id:0, name:1, price:1})
MongoDB Reference - find
MongoDB Reference - Query and Projection Operators
findOne()
db.collection.findOne(<query>)
db.collection.findOne(<query>, <projection>)
find()
と同じ使い方ができますが、メソッドの返り値はドキュメントになります。
無条件で検索する
> db.product.findOne()
または
> db.product.findOne({})
返り値はドキュメントなのでフィールドにアクセスできます。
> db.product.findOne({}).name
うまい棒
条件を指定して検索する
条件に一致するドキュメントが複数あっても1件しか取得しません。
> db.product.findOne({price:10})
取得するフィールドを選択する
> db.product.findOne({},{name:1, price:1})
findAndModify()
db.collection.findAndModify({
query: <document>,
sort: <document>,
remove: <boolean>,
update: <document>,
new: <boolean>,
fields: <document>,
upsert: <boolean>
})
取得と更新を行う
nameフィールドが"うまい棒"のドキュメントを返すと共にpriceフィールドを30に更新します。
> db.product.findAndModify({
query: {name:"うまい棒"},
update: {$set:{price:30}}
})
{
"_id" : ObjectId("5557d59cb636d6666833fb01"),
"no" : 1,
"name" : "うまい棒",
"price" : 10,
"variety" : [
{
"flavor" : "メンタイ",
"ppl" : 3
},
{
"flavor" : "サラミ",
"ppl" : 3
},
{
"flavor" : "ピザ",
"ppl" : 2
},
{
"flavor" : "オニオンサラダ",
"ppl" : 2
},
{
"flavor" : "コーンポタージュ",
"ppl" : 1
}
],
"snack" : true,
"activate" : true,
"update_dt" : ISODate("2014-12-31T15:00:00Z")
}
findAndModify()
が更新するドキュメントの件数は1件だけです。もしqueryの条件が複数のドキュメントに一致した場合、更新は最初のドキュメントに行います。
この例ではpriceフィールドが60のドキュメントを対象にしていますが、noフィールドの降順にソートしているため、更新されるのは"すこんぶ"になります。
/* priceフィールドが60のドキュメントは2件 */
> db.product.find({price:60},{_id:0,no:1,name:1,price:1})
{ "no" : 8, "name" : "フエラムネ", "price" : 60 }
{ "no" : 18, "name" : "すこんぶ", "price" : 60 }
> db.product.findAndModify({
query: {price:60},
update: {$set:{price:65}},
sort: {no:-1}
})
{
"_id" : ObjectId("5557c76db636d6666833fb00"),
"no" : 18,
"name" : "すこんぶ",
"activate" : true,
"update_dt" : ISODate("2015-05-31T15:00:00Z"),
"price" : 60
}
queryの条件が一致するドキュメントが存在しなかった場合は、更新も追加もされません。
> db.product.findAndModify({
query: {no:16},
update: {no:16, name:"ボンタンアメ", price:100, activate:false, update_dt:ISODate("2015-05-15T00:00:00+09:00")}
})
null
/* 追加されていないのでドキュメントは見つかりません */
> db.product.find({no:16},{_id:0,no:1,name:1,price:1})
>
upsert:true
を指定すると、queryの条件に一致するドキュメントが見つからなかった場合に追加を行います。
> db.product.findAndModify({
query: {no:16},
update: {no:16, name:"ボンタンアメ", price:100, activate:false, update_dt:ISODate("2015-05-15T00:00:00+09:00")},
upsert:true
})
null
/* upsert:trueを指定することでドキュメントを追加することができました */
> db.product.find({no:16},{_id:0,no:1,name:1,price:1})
{ "no" : 16, "name" : "ボンタンアメ", "price" : 100 }
new:true
を指定すると、更新後の(追加した場合は追加した)ドキュメントを返します。(追加の場合はnullを返します。)
> db.product.findAndModify({
query: {no:17},
update: {no:17, name:"スモモちゃん", price:40, activate:false, update_dt:ISODate("2015-05-30T00:00:00+09:00")},
upsert: true,
new: true
})
{
"_id" : ObjectId("5557c5e436efe7aa0e474d31"),
"no" : 17,
"name" : "スモモちゃん",
"price" : 40,
"activate" : false,
"update_dt" : ISODate("2015-05-29T15:00:00Z")
}
取得と削除を行う
nameフィールドが"うまい棒"のドキュメントを返すと共にそのドキュメントを削除します。
> db.product.findAndModify({
query: {name:"うまい棒"},
remove: true
})
{
"_id" : ObjectId("5557d59cb636d6666833fb01"),
"no" : 1,
"name" : "うまい棒",
"price" : 30,
"variety" : [
{
"flavor" : "メンタイ",
"ppl" : 3
},
{
"flavor" : "サラミ",
"ppl" : 3
},
{
"flavor" : "ピザ",
"ppl" : 2
},
{
"flavor" : "オニオンサラダ",
"ppl" : 2
},
{
"flavor" : "コーンポタージュ",
"ppl" : 1
}
],
"snack" : true,
"activate" : true,
"update_dt" : ISODate("2014-12-31T15:00:00Z")
}
/* 削除されたのでドキュメントは見つかりません */
> db.product.find({name:"うまい棒"})
>
[MongoDB Reference - findAndModify] (http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/)
cursorオブジェクト
find()
はcursorオブジェクトを返します。cursorオブジェクトにはcount()
、forEach()
、limit()
、sort()
などのメソッドがあります。
なお、findOne()
はcursorオブジェクトではなくdocumentオブジェクトを返します。
下記のようにcursorオブジェクトを変数に保存して処理を行うことができます。
> var c = db.product.find().limit(3)
> while (c.hasNext()) { print(c.next().name); }
ポテトフライ
きなこ棒
生いきビール
cursorオブジェクトの主なメソッド
count()
カーソルが返すドキュメントの件数を取得します。
> db.product.find().count()
17
コレクションにもcount()
がありますので、下記のようにしても件数を取得することができます。
> db.product.count()
17
コレクションのcount()
は引数にqueryを渡すことが可能です。
> db.product.count({price:10})
5
findOne()
はcursorオブジェクトを返さないためエラーになります。
> db.product.findOne().count()
2015-05-17T07:35:12.954+0900 E QUERY TypeError: Object [object Object] has no
method 'count'
at (shell):1:22
forEach()
検索したドキュメント個々に対して任意の処理を実行します。
> db.product.find().forEach(function(doc){ print(doc.name); })
うまい棒
ポテトフライ
きなこ棒
生いきビール
フルーツヨーグル
コーヒー牛乳キャンディ
ミニコーラ
フエラムネ
こざくら餅
たまごアイス
餅太郎
あんこ玉
ラムネ
みかん水
さくら大根
ボンタンアメ
スモモちゃん
hasNext() / next()
> var cursor = db.product.find()
> while(cursor.hasNext()) {
printjsononeline(cursor.next());
}
limit()
カーソルが返すドキュメントの最大件数を設定します。
> db.product.find({},{_id:0,no:1, name:1,price:1}).limit(5)
{ "no" : 1, "name" : "うまい棒", "price" : 10 }
{ "no" : 2, "name" : "ポテトフライ", "price" : 30 }
{ "no" : 3, "name" : "きなこ棒", "price" : 10 }
{ "no" : 4, "name" : "生いきビール", "price" : 40 }
{ "no" : 5, "name" : "フルーツヨーグル", "price" : 20 }
sort()
カーソルが返すドキュメントの並び順を指定します。ソートしたいフィールド名と並び順を「1:昇順」「-1:降順」で指定します。
> db.product.find({},{_id:0,no:1, name:1,price:1}).sort({price:1, no:1})
{ "no" : 15, "name" : "さくら大根" }
{ "no" : 1, "name" : "うまい棒", "price" : 10 }
{ "no" : 3, "name" : "きなこ棒", "price" : 10 }
{ "no" : 6, "name" : "コーヒー牛乳キャンディ", "price" : 10 }
{ "no" : 10, "name" : "たまごアイス", "price" : 10 }
{ "no" : 12, "name" : "あんこ玉", "price" : 10 }
{ "no" : 5, "name" : "フルーツヨーグル", "price" : 20 }
{ "no" : 9, "name" : "こざくら餅", "price" : 20 }
{ "no" : 2, "name" : "ポテトフライ", "price" : 30 }
{ "no" : 7, "name" : "ミニコーラ", "price" : 30 }
{ "no" : 11, "name" : "餅太郎", "price" : 30 }
{ "no" : 13, "name" : "ラムネ", "price" : 30 }
{ "no" : 4, "name" : "生いきビール", "price" : 40 }
{ "no" : 14, "name" : "みかん水", "price" : 40 }
{ "no" : 17, "name" : "スモモちゃん", "price" : 40 }
{ "no" : 8, "name" : "フエラムネ", "price" : 60 }
{ "no" : 16, "name" : "ボンタンアメ", "price" : 100 }
skip()
カーソルが返すドキュメントを指定した件数だけskipします。
> db.product.find({},{_id:0,no:1,name:1,price:1}).sort({no:1}).skip(5).limit(3)
{ "no" : 6, "name" : "コーヒー牛乳キャンディ", "price" : 10 }
{ "no" : 7, "name" : "ミニコーラ", "price" : 30 }
{ "no" : 8, "name" : "フエラムネ", "price" : 60 }
explain()
クエリの実行計画を確認します。
> db.product.find().explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.product",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [ ]
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"$and" : [ ]
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "localhost",
"port" : 27017,
"version" : "3.0.2",
"gitVersion" : "6201872043ecbbc0a4cc169b5482dcf385fc464f"
},
"ok" : 1
}
pretty()
ドキュメントを見やすいフォーマットに整形して出力します。
> db.product.find({no:1},{name:1,price:1,variety:1}).pretty()
{
"_id" : ObjectId("5557c280b636d6666833faf1"),
"name" : "うまい棒",
"price" : 10,
"variety" : [
{
"flavor" : "メンタイ",
"ppl" : 3
},
{
"flavor" : "サラミ",
"ppl" : 3
},
{
"flavor" : "ピザ",
"ppl" : 2
},
{
"flavor" : "オニオンサラダ",
"ppl" : 2
},
{
"flavor" : "コーンポタージュ",
"ppl" : 1
}
]
}
[MongoDB Manual - Cursors] (http://docs.mongodb.org/manual/core/cursors/)
MongoDB Reference - Cursor methods
insert()
db.collection.insert(
<document or array of documents>,
{ writeConcern: <document>, ordered: <boolean> }
)
新規作成
ドキュメントを作成します。
> db.product.insert({no:18, name:"すこんぶ", price:60, activate:true, update_dt:ISODate("2015-06-01T00:00:00+09:00")})
WriteResult({ "nInserted" : 1 })
insert()
は実行結果をWriteResultオブジェクトとして返します。
> var ws = db.product.insert({no:18, name:"すこんぶ", price:60, activate:true, update_dt:ISODate("2015-06-01T00:00:00+09:00")})
> printjson(ws)
{ "nInserted" : 1 }
bulk insert
複数件をまとめてインサートするにはデータを配列で渡します。
> db.product.insert([
{...},
{...},
{...}
])
または、bulkオペレーションメソッドを使用します。
> var bulk = db.product.initializeOrderedBulkOp()
> bulk.insert({...})
> bulk.insert({...})
> bulk.insert({...})
> bulk.execute()
bulkインサートは実行結果をBulkWriteResultとして返します。
> var ws = bulk.execute()
> printjson(ws)
{
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 14,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
}
MongoDB Reference - insert
MongoDB Reference - Bulk Operation Methods
update()
db.collection.update(
<query>,
<update>,
{ upsert: <boolean>, multi: <boolean>, writeConcern: <document> }
)
フィールドの更新
update()
の第1引数(query)に更新条件を、第2引数(update)に更新内容を記述します。
$set
を使用するとフィールドの値を置換することができます。
> db.product.findOne({name:"うまい棒"}).price
10
> db.product.update(
{name:"うまい棒"},
{$set:{price:25}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.product.findOne({name:"うまい棒"}).price
25
$set
を使用せず次のような操作を行うとドキュメント自体が更新されます。
> db.product.update(
{_id: ObjectId("5557c280b636d6666833faf1"},
{price:35}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.product.findOne({_id:ObjectId("5557c280b636d6666833faf1")})
{ "_id" : ObjectId("5557c280b636d6666833faf1"), "price" : 35 }
Update Operators
$set
,$unset
,$inc
などをUpdate Operatorといいます。
$set
上記のとおりです。
$inc
$inc
を使用するとフィールドの値をインクリメントすることができます。(マイナス値を使用すればデクリメントもできます。)
この例では、"きなこ棒"のpriceフィールドに5を加算します。
> db.product.findOne({name:"きなこ棒"}).price
10
> db.product.update(
{name:"きなこ棒"},
{$inc:{price:5}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.product.findOne({name:"きなこ棒"}).price
15
$min / $max
$min
/$max
を使用すると条件付きでフィールドの値を変更することができます。
$min
を使用すると現在の値より大きい値で更新はできなくなります。($max
はその逆の働きをします。)
この例では、"生いきビール"のpriceフィールドを40から50へ更新しようとしていますが、ドキュメントは更新されません。
> db.product.findOne(
{name:"生いきビール"},
{_id:0, name:1, price:1}
)
{ "name" : "生いきビール", "price" : 40 }
> db.product.update(
{name:"生いきビール"},
{$min:{price:50}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
現在の値より小さい値へ更新することは可能です。
> db.product.update(
{name:"生いきビール"},
{$min:{price:30}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.product.findOne(
{name:"生いきビール"},
{_id:0, name:1, price:1}
)
{ "name" : "生いきビール", "price" : 30 }
$currentDate
$currentDate
を使用すると指定したフィールドを現在日時で更新することができます。
> db.product.update(
{name:"生いきビール"},
{$currentDate:{update_dt: {$type: "date"}}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
更新対象が見つからなかった場合
queryで指定する更新対象のドキュメントが見つからなかった場合は、ドキュメントは追加も更新もされません。
> db.product.update(
{no:19},
{no:19, name:"ハートチップル", price:100, activate:true, variety:[{flavor:"ニンニク", ppl:2}], snack:true, update_dt:ISODate("2015-06-01T00:00:00+09:00")}
)
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
upsert:true
を指定すること更新対象がなかった場合にドキュメントを追加することができます。
> db.product.update(
{no:19},
{no:19, name:"ハートチップル", price:100, activate:true, variety:[{flavor:"ニンニク", ppl:2}], snack:true, update_dt:ISODate("2015-06-01T00:00:00+09:00")},
{upsert:true}
)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("5557cb2736efe7aa0e474d32")
})
upsertでinsertの時にだけフィールドを更新する
$setOnInsert
で指定するフィールドはドキュメントのinsert時にしか更新されません。
この例ではinsert時にだけcreate_dtフィールドを現在日時で更新します。
> db.product.findOne({no:20})
null
> db.product.update(
{no:20},
{$set:{no:20, name:"きびだんご", price:100, activate:true, update_dt:ISODate()}, $setOnInsert:{create_dt:ISODate()}},
{upsert:true}
)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("5557cda836efe7aa0e474d34")
})
> db.product.findOne({no:20},{_id:0,no:1,name:1,price:1,update_dt:1,create_dt:1})
{
"no" : 20,
"name" : "きびだんご",
"price" : 100,
"update_dt" : ISODate("2015-05-16T23:07:20.636Z"),
"create_dt" : ISODate("2015-05-16T23:07:20.636Z")
}
priceフィールドの値を変えてもう一度updateを行います。
priceフィールドとupdate_dtフィールドは更新されていますが、create_dtフィールドはinsert時のときのままです。
> db.product.update(
{no:20},
{$set:{no:20, name:"きびだんご", price:120, activate:true, update_dt:ISODate()}, $setOnInsert:{create_dt:ISODate()}},
{upsert:true}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.product.findOne({no:20},{_id:0,no:1,name:1,price:1,update_dt:1,create_dt:1})
{
"no" : 20,
"name" : "きびだんご",
"price" : 120,
"update_dt" : ISODate("2015-05-16T23:08:13.973Z"),
"create_dt" : ISODate("2015-05-16T23:07:20.636Z")
}
フィールドのリネーム
フィールドをリネームするには$rename
を使用します。ドキュメント全てを対象にする場合はmulti:true
を指定します。
> db.product.update(
{},
{$rename:{"price":"unit_price"}}, {multi:true}
)
WriteResult({ "nMatched" : 19, "nUpserted" : 0, "nModified" : 18 })
/* priceフィールドがunit_priceフィールドに変わっています */
> db.product.find({}, {_id:0, name:1, price:1, unit_price:1}).limit(5)
{ "name" : "ポテトフライ", "unit_price" : 30 }
{ "name" : "きなこ棒", "unit_price" : 15 }
{ "name" : "生いきビール", "unit_price" : 30 }
{ "name" : "フルーツヨーグル", "unit_price" : 20 }
{ "name" : "コーヒー牛乳キャンディ", "unit_price" : 10 }
複数件の更新
複数のドキュメントが更新対象になる場合、実際に更新されるのは最初の1件だけです。
> db.product.find({price:10},{_id:0,name:1,price:1})
{ "name" : "うまい棒", "price" : 10 }
{ "name" : "コーヒー牛乳キャンディ", "price" : 10 }
{ "name" : "たまごアイス", "price" : 10 }
{ "name" : "あんこ玉", "price" : 10 }
> db.product.update(
{price:10},
{$set:{price:15}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
条件に一致する全てのドキュメントを更新するには、multi:true
を指定します。
> db.product.update(
{price:10},
{$set:{price:15}},
{multi:true}
)
WriteResult({ "nMatched" : 4, "nUpserted" : 0, "nModified" : 4 })
フィールドの追加
更新するフィールドがドキュメントに無い場合は、そのフィールドがドキュメントに追加されます。
この例では、"うまい棒"のドキュメントにdescフィールドを追加しています。
> db.product.update(
{name:"うまい棒"},
{$set:{desc:"伝統のスナック菓子"}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.product.find({name:"うまい棒"}).pretty()
{
"_id" : ObjectId("5557d975b636d6666833fb02"),
"no" : 1,
"name" : "うまい棒",
"price" : 10,
"variety" : [
{
"flavor" : "メンタイ",
"ppl" : 3
},
{
"flavor" : "サラミ",
"ppl" : 3
},
{
"flavor" : "ピザ",
"ppl" : 2
},
{
"flavor" : "オニオンサラダ",
"ppl" : 2
},
{
"flavor" : "コーンポタージュ",
"ppl" : 1
}
],
"snack" : true,
"activate" : true,
"update_dt" : ISODate("2014-12-31T15:00:00Z"),
"desc" : "伝統のスナック菓子"
}
フィールドの削除
$unset
を使用するとドキュメントからフィールドを削除することができます。
> db.product.update(
{name:"うまい棒"},
{$unset:{price:""}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.product.find({name:"うまい棒"}).pretty()
{
"_id" : ObjectId("5557d975b636d6666833fb02"),
"no" : 1,
"name" : "うまい棒",
"variety" : [
{
"flavor" : "メンタイ",
"ppl" : 3
},
{
"flavor" : "サラミ",
"ppl" : 3
},
{
"flavor" : "ピザ",
"ppl" : 2
},
{
"flavor" : "オニオンサラダ",
"ppl" : 2
},
{
"flavor" : "コーンポタージュ",
"ppl" : 1
}
],
"snack" : true,
"activate" : true,
"update_dt" : ISODate("2014-12-31T15:00:00Z"),
"desc" : "伝統のスナック菓子"
}
MongoDB Reference - update
MongoDB Reference - Update Operators
save()
db.collection.save(
<document>,
{ writeConcern: <document> }
)
追加または更新
update()
は更新対象のドキュメントをqueryで指定できますが、save()
はqueryを指定することはできません。
代わりに_id
が指定されていて当該のドキュメントがあればupdateを行い、無ければinsertします。
> db.product.save(
{no:21, name:"ふ菓子", price:10, activate:false, update_dt:ISODate("2015-05-30T00:00:00+09:00")}
)
WriteResult({ "nInserted" : 1 })
_id
が指定されていて且つそのid値が存在する場合は更新します。(id値が存在しない場合は追加)
> db.product.save(
{_id:ObjectId("5557daa5b636d6666833fb03"), no:21, name:"ふ菓子", price:20, activate:true, update_dt:ISODate("2015-05-30T00:00:00+09:00")}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
update()との違い
- queryで更新対象を指定できない
- 複数件の同時更新ができない
- upadte()、findAndModify()では使用できるupdate operatorが使用できない
remove()
db.collection.remove(
<query>,
<justOne>
)
すべて削除
> db.product.remove({})
WriteResult({ "nRemoved" : 14 })
条件を指定して削除
> db.product.remove({activate:false})
WriteResult({ "nRemoved" : 2 })
1件だけ削除
第2引数(justOne)にtrueを渡すと1件だけ削除します。
> db.product.remove({}, true)
WriteResult({ "nRemoved" : 1 })
remove()
は実行結果をWriteResultオブジェクトとして返します。
> var wr = db.product.remove({}, true)
> printjson(wr)
{ "nRemoved" : 1 }
index
indexの確認
> db.product.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.product"
}
]
indexの作成
db.collection.createIndex(keys, options)
フィールドに1を指定すると昇順、-1を指定すると降順になります。
> db.product.createIndex({price:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
/* 作成したインデックスを確認してみます */
> db.product.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.product"
},
{
"v" : 1,
"key" : {
"price" : 1
},
"name" : "price_1",
"ns" : "test.product"
},
]
/* 名前を指定して削除します */
> db.product.dropIndex("price_1")
{ "nIndexesWas" : 2, "ok" : 1 }
オプションでindex名を指定することができます。
> db.product.createIndex(
{price:1},
{name:"price_idx01"}
)
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
ユニークindexの作成
作成時のオプションでunique:true
を指定します。
> db.product.createIndex(
{name:1},
{unique:true, name:"name_uni01"}
)
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
ユニークindexを作成したフィールドには重複したデータを登録することはできませんが、追加するドキュメントにそのフィールドが無かった場合、フィールドの値はnullとして扱われるようです。
[MongoDB manual - unique index and missing field] (http://docs.mongodb.org/manual/tutorial/create-a-unique-index/#unique-index-and-missing-field)
試しに、nameフィールドにユニークindexを作成した状態で、nameフィールドが無いドキュメントを追加してみます。
1件目は追加することができました。
> db.product.insert(
{no:22, price:30, activate:true, update_dt:ISODate("2015-05-30T00:00:00+09:00")}
)
WriteResult({ "nInserted" : 1 })
もう一度nameフィールドが無いドキュメントを追加しようとするとエラーになります。これはnull値も重複のチェックの対象になっているためのようです。
> db.product.insert(
{no:23, price:30, activate:true, update_dt:ISODate("2015-05-30T00:00:00+09:00")}
)
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error index: test.product.$name
_uni01 dup key: { : null }"
}
})
この場合は、ユニークindex作成時にsparse:true
を併用することでnullを無視することができます。
/* ユニークindexを作り直すために削除 */
> db.product.dropIndex("name_uni01")
{ "nIndexesWas" : 3, "ok" : 1 }
/* ユニークindexを作成 */
> db.product.createIndex(
{name:1},
{unique:true, sparse:true, name:"name_uni01"}
)
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
/* nameフィールドの無いドキュメントを追加 */
> db.product.insert(
{no:23, price:30, activate:true, update_dt:ISODate(
"2015-05-30T00:00:00+09:00")}
)
WriteResult({ "nInserted" : 1 })
/* nameフィールドの無いドキュメントを追加することができました */
> db.product.find({name:{$exists:false}},{_id:1,no:1,name:1})
{ "_id" : ObjectId("5557db82b636d6666833fb04"), "no" : 22 }
{ "_id" : ObjectId("5557dbf5b636d6666833fb06"), "no" : 23 }
TTLインデックス
時間経過によってドキュメントを自動的に削除したい場合、expireAfterSecondsを使用したインデックスを作成します。
この例ではdelete_dtフィールドにexpireAfterSecondsを300秒(5分)に設定したTTLインデックスを作成しています。
> db.product.createIndex(
{delete_dt:1},
{expireAfterSeconds:300, name:"ttl_idx"}
)
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 3,
"numIndexesAfter" : 4,
"ok" : 1
}
ためしに"コーヒー牛乳キャンディ"のドキュメントのdelete_dtを現在日時で更新します。
更新してから5分経過後にもう一度検索すると削除されていることがわかります。
> db.product.update(
{name:"コーヒー牛乳キャンディ"},
{$set:{delete_dt:new Date()}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.product.find(
{name:"コーヒー牛乳キャンディ"},
{_id:0,name:1,delete_dt:1}
)
{ "name" : "コーヒー牛乳キャンディ", "delete_dt" : "Sun May 17 2015 09:10:36 GMT
+0900 (東京 (標準時))" }
5分経過後に検索するとドキュメントは見つかりません。
> db.product.find(
{name:"コーヒー牛乳キャンディ"},
{_id:0,name:1,delete_dt:1}
)
>
MongoDB Reference - createIndex
MongoDB Manual - Sparse Indexes
MongoDB Manual - Expire Data from Collections by Setting TTL
indexの削除
インデックスの名前を指定して削除します。
> db.product.dropIndex("price_idx01")
{ "nIndexesWas" : 4, "ok" : 1 }
"product"コレクションの(_id
以外の)すべてのindexを削除します。
> db.product.dropIndexes()
{
"nIndexesWas" : 3,
"msg" : "non-_id indexes dropped for collection",
"ok" : 1
}
rename
db.collection.renameCollection(target, dropTarget)
"product"コレクションの名前を"newProduct"にリネームします。
> db.product.renameCollection("newProduct")
{ "ok" : 1 }
指定した"newProduct"コレクションが既に存在する場合はエラーになります。
{ "ok" : 0, "errmsg" : "target namespace exists" }
第2引数(dropTarget)にtrueを指定した場合、既に"newProduct"コレクションがある場合はそのコレクションを削除し、その後に"product"を"newProduct"へリネームします。
> db.product.renameCollection("newProduct", true)
{ "ok" : 1 }
drop()
db.collection.drop()
"product"コレクションを削除します。
> db.product.drop()
true
store javascript function
登録する
> db.system.js.save({
_id:"add",
value:function(a, b) { return a + b; }
})
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "add" })
登録されているfunctionを調べる
> db.system.js.find()
{ "_id" : "add", "value" : function (a, b) { return a + b; } }
使用する
> db.loadServerScripts()
> var f = db.system.js.findOne({_id:"add"}).value
> f(2,3)
5
削除する
> db.system.js.remove({_id:"add"})
WriteResult({ "nRemoved" : 1 })
日付
Date()
Unixエポックからのミリ秒数(1970年1月1日)を表す64ビットの整数です。
> var dt = new Date()
> dt.toString()
Sun May 17 2015 06:25:43 GMT+0900 (東京 (標準時))
ISODate()
Date()
のラッパー関数で返される値はDateです。
> var iso = ISODate()
> iso.toString()
Sun May 17 2015 06:25:43 GMT+0900 (東京 (標準時))
> iso instanceof Date
true
> iso instanceof ISODate
false
任意の日時を生成するにはISODate()
に基本形式か拡張形式の日時表記文字列を渡します。
- 基本形式
- "20150510T102322+0900"
- 拡張形式
- "2015-05-10T10:23:22+09:00"
世界協定時(UTC)として表現する場合は最後に"Z"を付けます。
ISODate("2015-05-10T00:00:00Z")
日本標準時(UTC+9)の場合は"+0900"または"+09:00"を付けます。
ISODate("2015-05-10T09:00:00+09:00")
> var iso = ISODate("2015-05-15T12:00:01+09:00")
> iso.toString()
Fri May 15 2015 12:00:01 GMT+0900 (東京 (標準時))
Timestamp()
MongoDB内部で使用されているデータ型で、通常のアプリケーションではDate型で十分らしいです。
> var ts = new Timestamp()
> ts.toString()
Timestamp(0, 0)
[MongoDB reference - Date] (http://docs.mongodb.org/manual/reference/bson-types/#date)
[MongoDB reference - Timpstamps] (http://docs.mongodb.org/manual/reference/bson-types/#timestamps)
shellのカスタマイズ
find()
の一度に取得する件数を変えます。デフォルトは20です。
> DBQuery.shellBatchSize = 10
10
shellの出力のデフォルトをpretty printにします。
> DBQuery.prototype._prettyShell = true
true
下記のようなjavascriptを実行してpromptをカスタマイズできます。
> cmdCount = 1;
> host = db.serverStatus().host;
> prompt = function() {
return db + "@" + host + "(" + (cmdCount++) + ")> ";
}
test@localhost(1)>
.mongorc.js
ホームディレクトリにある.mongorc.jsに、shell起動時に実行したいスクリプトを記述することができます。
Native Methods
load()
load()
は引数で指定されたjavascriptファイルをロードして実行します。
この例では、下記のjavascriptをsample.jsファイルとして用意しmongo shellにロードします。
function randomStr() {
return Math.random().toString(36);
}
var col = new Array("red","blue","yellow","green","white");
function randomColor() {
return col[Math.floor(Math.random() * 5)];
}
var act = new Array(true, false);
function randomAct() {
return act[Math.floor(Math.random() * 2)];
}
function createTestData() {
for (var idx = 0; idx<100000; idx++) {
db.sample.insert({no:idx, color:randomColor(), desc:randomStr(), activate:randomAct(), create_dt:new Date()});
}
}
sample.jsをロードします。
> load("sample.js")
true
createTestData()を実行するとsampleコレクションにテストデータを10万件作成します。
> createTestData()
> db.sample.find().count()
100000
その他の主なNativeメソッド
Name | Description |
---|---|
cat() | Returns the contents of the specified file. |
version() | Returns the current version of the mongo shell instance. |
hostname() | Returns the hostname of the system running the shell. |
load() | Loads and runs a JavaScript file in the shell. |
ls() | Returns a list of the files in the current directory. |
quit() | Exits the current shell session. |
_rand() | Returns a random number between 0 and 1. |