LoginSignup
15
15

More than 5 years have passed since last update.

7つのデータベース7つの世界 MongoDB メモ

Last updated at Posted at 2014-09-09

はじめに

7つのデータベース 7つの世界の第5章 MongoDBのメモです。

1日目

MongoDBインストール

1日目の宿題

やってみよう

1.

JSONドキュメント{ "hello" : "world" }の中身を印字してみよう。

> db.yattemiyo.insert({"hello": "world"})
WriteResult({ "nInserted" : 1 })
> print(JSON.stringify(db.yattemiyo.findOne({hello: "world"}, {_id: false})))
{"hello":"world"}
>

2.

大文字小文字を区別しない正規表現を使って、文字列newが含まれる町を選択してみよう。

> db.towns.find({name: /new/i})
{ "_id" : ObjectId("540bd726c265200143a187d6"), "name" : "New York", "population" : 22200000, "last_census" : ISODate("2009-07-31T00:00:00Z"), "famous_for" : [ "statue of liberty", "food" ], "mayor" : { "name" : "Michael Bloomberg", "party" : "I" } }
>

3.

名前にeが含まれていて、foodかbeerで有名な市をすべて検索してみよう。

> db.towns.find({name: /e/, famous_for: {$in: ["food", "beer"]}})
{ "_id" : ObjectId("540bd726c265200143a187d6"), "name" : "New York", "population" : 22200000, "last_census" : ISODate("2009-07-31T00:00:00Z"), "famous_for" : [ "statue of liberty", "food" ], "mayor" : { "name" : "Michael Bloomberg", "party" : "I" } }
>

4.

新しいデータベース「blogger」とコレクション「articles」を作ってみよう。新しい記事に作者の名前・メールアドレス・作成日・本文を挿入してみよう。

> use blogger
switched to db blogger
> db.articles.insert({author: "nownabe", email: "nownabe@hogehoge.com", created_on: ISODate("2014-09-09"), text: "foo\nbar"})
WriteResult({ "nInserted" : 1 })
> db.articles.find()
{ "_id" : ObjectId("540f1cc1128b0ea47aa14735"), "author" : "nownabe", "email" : "nownabe@hogehoge.com", "created_on" : ISODate("2014-09-09T00:00:00Z"), "text" : "foo\nbar" }
>

5.

名前と本文を持つコメントの配列を記事に追加してみよう。

> db.articles.update({_id: ObjectId("540f1cc1128b0ea47aa14735")}, {$set: {comments: [{name: "kani", text: "hyoe"}]}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.articles.find()
{ "_id" : ObjectId("540f1cc1128b0ea47aa14735"), "author" : "nownabe", "email" : "nownabe@hogehoge.com", "created_on" : ISODate("2014-09-09T00:00:00Z"), "text" : "foo\nbar", "comments" : [ { "name" : "kani", "text" : "hyoe" } ] }
>

6.

外部のJavascriptファイルにあるクエリを実行してみよう。

$ echo '"count(countries): " + db.countries.count()' > day1-6.js
$ mongo --quiet book < day1-6.js

2日目

2日目の宿題

調べてみよう

1.

adminコマンドのショートカットを探してみよう。

> db.adminCommand
function ( obj ){
    if ( this._name == "admin" )
        return this.runCommand( obj );
    return this.getSiblingDB( "admin" ).runCommand( obj );
}
>

2.

クエリとカーソルのオンラインドキュメントを探してみよう。

3.

MongoDBのmapreduceのドキュメントを探してみよう。

4. JavaScriptのインターフェイスを使って、help()・findOne()・stats()の3つの関数を調査してみよう。

> db.cities.help
> db.cities.findOne
> db.cities.stats

やってみよう

1.

カウントの合計値を出力するfinalize()メソッドを実装してみよう。

※おそらく、code/mongo/reduce_2.jsのようなコードにしなくてもいいように出力のキーをcountからtotalにしろって話

shukudai2-1.js
reduce = function(key, values){
  var total = 0;
  for(var i=0; i<values.length; i++) {
    total += values[i].count
  }
  return {count: total}
}

finalize = function(key, value) {
  return {total: value.count}
}

results = db.runCommand({
  mapReduce: "phones",
  map: map,
  reduce: reduce,
  out: "phones.report2",
  finalize: finalize
})

2.

あなたが選んだ言語のドライバをインストールして、データベースに接続してみよう。コレクションを作って、フィールドにインデックスを作成してみよう。

Rubyでやりました。
http://docs.mongodb.org/ecosystem/drivers/ruby/

shukudai2-2.rb
require 'mongo'
client = Mongo::MongoClient.new
db = client["book"]
coll = db["shukudai_2_2"]
coll.remove

1.upto(100) do |i|
  coll.insert({
    _id: i,
    created_at: Time.now,
    fizzbuzz: [i%3, i%5].include?(0) ? ( (i%3).zero? ? "fizz" : "" ) + ( (i%5).zero? ? "buzz" : "") : i
  })
end

気づいたらfizzbuzzになってました。

3日目

3日目の宿題

調べてみよう

1.

レプリカセットの設定オプションについて、オンラインドキュメントで調べてみよう

2.

球体ジオインデックスの作り方を探してみよう

やってみよう

1.

Mongoは、境界となる形(四角形や丸)をサポートしている。ロンドンの中心から50マイル四方の範囲にあるすべての都市を見つけてみよう。

MongoDBのクエリでは四角形の左下と右上の座標を2つ渡す必要があるので、それを計算する。
http://docs.mongodb.org/manual/reference/operator/query/box/

ロンドンのGeoは[51.507778, -0.128056]らしい。
GeoHackより)

このGeoってのは[Latitude, Longtitude][緯度, 経度])になってる。

また、1マイル=1.6kmとすると50マイル=80km。
地球は周囲4万キロの真球として計算する。

緯度は簡単に計算できる。
90 / 40000 * 80 = 0.18
なので、ロンドンの南北50マイルのGeoは、[51.327778, -0.128056][51.687778, -0.128056]

経度はちょっと複雑になる。
経度と距離の関係は、緯度によって変化する。
しかし、ココによると過剰な精度はいらぬと書いてあるので、このページの表を参考にする。
といっても緯度50度の値はないので、だいたい1度70kmぐらいだろうってことにする。

すると、50マイルというのは80 / 70 = 1.1429度になる。

よって、ロンドンの50マイル四方で南西の座標は[51.327778, -1.270956]、北東の座標は[51.687778, 1.014844]となる。

mongo
mongos> db.cities.find({location: {$geoWithin: {$box: [[51.327778, -1.270956], [51.687778, 1.014844]]}}})
{ "_id" : ObjectId("541e7dc1051a80368833da31"), "name" : "Holborn", "country" : "GB", "timezone" : "Europe/London", "population" : 22000, "location" : { "latitude" : 51.52124, "longitude" : -0.11347 } }
{ "_id" : ObjectId("541e7dc1051a80368833d486"), "name" : "London", "country" : "GB", "timezone" : "Europe/London", "population" : 7556900,"location" : { "latitude" : 51.50853, "longitude" : -0.12574 } }
{ "_id" : ObjectId("541e7dc1051a80368833d6b0"), "name" : "Farnham Royal", "country" : "GB", "timezone" : "Europe/London", "population" : 6187, "location" : { "latitude" : 51.53333, "longitude" : -0.61667 } }
{ "_id" : ObjectId("541e7dc1051a80368833d310"), "name" : "Potters Bar", "country" : "GB", "timezone" : "Europe/London", "population" : 22192, "location" : { "latitude" : 51.68333, "longitude" : -0.16667 } }
{ "_id" : ObjectId("541e7dc1051a80368833da43"), "name" : "Gerrards Cross", "country" : "GB", "timezone" : "Europe/London", "population" : 7342, "location" : { "latitude" : 51.5895, "longitude" : -0.55043 } }
{ "_id" : ObjectId("541e7dc1051a80368833d2f4"), "name" : "Radlett", "country" : "GB", "timezone" : "Europe/London", "population" : 8213, "location" : { "latitude" : 51.68333, "longitude" : -0.31667 } }
{ "_id" : ObjectId("541e7dc1051a80368833d943"), "name" : "Beaconsfield", "country" : "GB", "timezone" : "Europe/London", "population" : 12566, "location" : { "latitude" : 51.6, "longitude" : -0.63333 } }
{ "_id" : ObjectId("541e7dc1051a80368833d0cc"), "name" : "Windlesham", "country" : "GB", "timezone" : "Europe/London", "population" : 4194, "location" : { "latitude" : 51.36667, "longitude" : -0.65 } }
{ "_id" : ObjectId("541e7dc1051a80368833d9c7"), "name" : "Amersham", "country" : "GB", "timezone" : "Europe/London", "population" : 21731, "location" : { "latitude" : 51.66667, "longitude" : -0.61667 } }
{ "_id" : ObjectId("541e7dc1051a80368833d371"), "name" : "Ottershaw", "country" : "GB", "timezone" : "Europe/London", "population" : 3451, "location" : { "latitude" : 51.35, "longitude" : -0.53333 } }
{ "_id" : ObjectId("541e7dc1051a80368833d831"), "name" : "Chalfont Saint Peter", "country" : "GB", "timezone" : "Europe/London", "population" : 20059, "location" : { "latitude" : 51.60885, "longitude" : -0.55618 } }
{ "_id" : ObjectId("541e7dc1051a80368833d37a"), "name" : "Old Windsor", "country" : "GB", "timezone" : "Europe/London", "population" : 7168, "location" : { "latitude" : 51.45, "longitude" : -0.58333 } }
{ "_id" : ObjectId("541e7dc1051a80368833d832"), "name" : "Chalfont Saint Giles", "country" : "GB", "timezone" : "Europe/London", "population" : 4815, "location" : { "latitude" : 51.63184, "longitude" : -0.57026 } }
{ "_id" : ObjectId("541e7dc1051a80368833d0cb"), "name" : "Windsor", "country" : "GB", "timezone" : "Europe/London", "population" : 28324, "location" : { "latitude" : 51.48333, "longitude" : -0.6 } }
{ "_id" : ObjectId("541e7dc1051a80368833da53"), "name" : "Amersham on the Hill", "country" : "GB", "timezone" : "Europe/London", "population" : 17719, "location" : { "latitude" : 51.67468, "longitude" : -0.60742 } }
{ "_id" : ObjectId("541e7dc1051a80368833d228"), "name" : "Slough", "country" : "GB", "timezone" : "Europe/London", "population" : 134072, "location" : { "latitude" : 51.5, "longitude" : -0.58333 } }
{ "_id" : ObjectId("541e7dc1051a80368833d75a"), "name" : "Denham", "country" : "GB", "timezone" : "Europe/London", "population" : 6548, "location" : { "latitude" : 51.56667, "longitude" : -0.5 } }
{ "_id" : ObjectId("541e7dc1051a80368833d250"), "name" : "Shepperton", "country" : "GB", "timezone" : "Europe/London", "population" : 10106, "location" : { "latitude" : 51.38333, "longitude" : -0.43333 } }
{ "_id" : ObjectId("541e7dc1051a80368833d601"), "name" : "Harefield", "country" : "GB", "timezone" : "Europe/London", "population" : 6683, "location" : { "latitude" : 51.6, "longitude" : -0.48333 } }
{ "_id" : ObjectId("541e7dc1051a80368833d1bf"), "name" : "Sunbury", "country" : "GB", "timezone" : "Europe/London", "population" : 27784, "location" : { "latitude" : 51.4, "longitude" : -0.4 } }
Type "it" for more
mongos>

2.

6つのサーバーを起動してみよう。2つのレプリカセットに3つのサーバーがあり、レプリカセットはいずれもシャードである。設定サーバーとmongosを起動してみよう。それらに対して、GridFSを実行してみよう。

$ mkdir data
$ cd data
$ mkdir mongod1{a,b,c} mongod2{a,b,c} mongo{c,s}
$ mongod --shardsvr --replSet rs1 --dbpath ./mongod1a --port 27011 --noprealloc --smallfiles --nojournal
$ mongod --shardsvr --replSet rs1 --dbpath ./mongod1b --port 27012 --noprealloc --smallfiles --nojournal
$ mongod --shardsvr --replSet rs1 --dbpath ./mongod1c --port 27013 --noprealloc --smallfiles --nojournal
$ mongod --shardsvr --replSet rs2 --dbpath ./mongod2a --port 27021 --noprealloc --smallfiles --nojournal
$ mongod --shardsvr --replSet rs2 --dbpath ./mongod2b --port 27022 --noprealloc --smallfiles --nojournal
$ mongod --shardsvr --replSet rs2 --dbpath ./mongod2c --port 27023 --noprealloc --smallfiles --nojournal
$ mongod --configsvr --dbpath ./mongoc --port 27018 --nojournal
$ mongos --configdb localhost:27018 --chunkSize 1 --port 27017
$ mongo localhost:27011
> rs.initiate({_id: "rs1", members: [
...   {_id: 1, host: "localhost:27011"},
...   {_id: 2, host: "localhost:27012"},
...   {_id: 3, host: "localhost:27013"}
... ]})
{
        "info" : "Config now saved locally.  Should come online in about a minute.",
        "ok" : 1
}
> exit
bye
$ mongo localhost:27021
> rs.initiate({_id: "rs2", members: [
...   {_id: 1, host: "localhost:27021"},
...   {_id: 2, host: "localhost:27022"},
...   {_id: 3, host: "localhost:27023"}
... ]})
{
        "info" : "Config now saved locally.  Should come online in about a minute.",
        "ok" : 1
}
> exit
bye
$ mongo admin
mongos> sh.addShard("rs1/localhost:27011,localhost:27012,localhost:27013")
{ "shardAdded" : "rs1", "ok" : 1 }
mongos> sh.addShard("rs2/localhost:27021,localhost:27022,localhost:27023")
{ "shardAdded" : "rs2", "ok" : 1 }
mongos> sh.enableSharding("test")
{ "ok" : 1 }
mongos> sh.shardCollection("test.cities", {name: 1})
{ "collectionsharded" : "test.cities", "ok" : 1 }
mongos> exit
bye
$ cd ~/code/mongo
$ mongoimport --db test --collection cities --type json mongo_cities1000.json
$ mongo
MongoDB shell version: 2.6.4
connecting to: test
mongos> sh.status()
--- Sharding Status ---
  sharding version: {
        "_id" : 1,
        "version" : 4,
        "minCompatibleVersion" : 4,
        "currentVersion" : 5,
        "clusterId" : ObjectId("541e9966c4aeff3a3ef20a54")
}
  shards:
        {  "_id" : "rs1",  "host" : "rs1/localhost:27011,localhost:27012,localhost:27013" }
        {  "_id" : "rs2",  "host" : "rs2/localhost:27021,localhost:27022,localhost:27023" }
  databases:
        {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
        {  "_id" : "test",  "partitioned" : true,  "primary" : "rs1" }
                test.cities
                        shard key: { "name" : 1 }
                        chunks:
                                rs2     8
                                rs1     17
                        too many chunks to print, use verbose if you want to force print

mongos> exit
bye
$ mongofiles put distinct_digits.js
connected to: 127.0.0.1
added file: { _id: ObjectId('541ea0bc7926af426fbf6bfa'), filename: "distinct_digits.js", chunkSize: 261120, uploadDate: new Date(1411293372268), md5: "b2ff3a355d0c6532933c60fe2a0d0592", length: 767 }
done!
$ mongofiles list
connected to: 127.0.0.1
distinct_digits.js      767
15
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
15