标签归档:mongodb

MongoDB翻页测试

翻页测试脚本:

<?php
$m = new MongoClient();
$db = $m->test;
$collection = $db->tester;
 
$page = isset($_GET['page'])?(int)$_GET['page']:1;
if($page < 1){ $page = 1; }

$pageSize = isset($_GET['pagesize'])?(int)$_GET['pagesize']:100;
if($pageSize < 1){
    $pageSize = 100;
}

$skip = ($page -1) * $pageSize;

////////////////////
$s = microtime(true);

$res = $collection->find(array('baz'=>array('$gt'=>2000000)),array("_id"=>0,"baz"=>1,"z"=>1))->skip($skip)->limit($pageSize);

echo "<!doctype html><html><head><meta charset='utf-8'></head><body>";

$p = $page -10; $total = 1000000;

$splitPage = '';
for($i=1;$i<20;$i++){
    if((($p+$i) <= 0) || (($p+$i) > $total)) continue;

    $splitPage .= "<a href='http://zf.vfeelit.com/mongodb.php?page=".(int)($p+$i)."&pagesize=$pageSize'>".(int)($p+$i)."</a> | ";
}

echo $splitPage;
echo "<table border='1'>";
echo "<tr><th>id</th><th>baz</th><th>page</th><th>pageSize</th><th>skip</th></tr>";
$i = 1;
foreach($res as $c){
	if($i>20) continue;
	echo "<tr>";
	echo "<td>".$c['baz']."</td>";
	echo "<td>".$c['z']."</td>";
	echo "<td>$page</td>";
	echo "<td>$pageSize</td>";
	echo "<td>".($skip+$i)."</td>";
	echo "</tr>";
	$i++;
}
echo "</table>";
echo $splitPage."<br />";

$e = microtime(true);

echo "Time Toke:".(float)($e-$s)."  (Start:$s End:$e) ";
echo "</body></html>";
?>

mongodb

虚拟机: 2G内存 CentOS 6.5 64位,MongoDB 3.0.2

数据总量500万。

#设置索引
db.tester.ensureIndex({"baz":1});
for(var i = 1; i < 5000000; i++){
    db.tester.insert({"baz":i,"z":i-1});
}
$res = $collection->find(array('baz'=>array('$gt'=>2000000)),array

("_id"=>0,"baz"=>1,"z"=>1))->skip($skip)->limit($pageSize);

baz字段添加了索引。数据从200万开始(’$gt’=>2000000)。

页大小为100
1 当页数是1时,即偏移量为0,Time Toke:0.0017759799957275 (Start:1430666966.9116 End:1430666966.9133)
2 当页数是10时,即偏移量为90,Time Toke:0.003978967666626 (Start:1430667014.0709 End:1430667014.0749)
3 当页数是100时,即偏移量为9900,Time Toke:0.026927947998047 (Start:1430667035.1938 End:1430667035.2207)
3 当页数是500时,即偏移量为49900,Time Toke:0.10729312896729 (Start:1430667714.8598 End:1430667714.9671)
4 当页数是1000时,即偏移量为99900,Time Toke:0.24366307258606 (Start:1430667090.5565 End:1430667090.8002)
5 当页数是5000时,即偏移量为499900,Time Toke:0.91205501556396 (Start:1430667214.3094 End:1430667215.2214)
6 当页数是10000时,即偏移量为999900,Time Toke:1.8545939922333 (Start:1430667307.2912 End:1430667309.1458)
6 当页数是20000时,即偏移量为499900,Time Toke:3.7924218177795 (Start:1430667337.8097 End:1430667341.6021)

偏移量在5万 – 50万之间,时间维持在毫秒级别,50万之后就上升到秒级别。从50万到100万到200万,时间也大概是前面的2倍关系。

MongoDB CRUD操作

任何的数据库,特别对开发人员,CRUD都是最基础、最重要的必须掌握的部分。

一 查询
1 find简述

查询所有或符合条件的文档

db.c.find()
db.c.find({})
db.c.find({“age”:27})
db.c.find({“username”:”vfeelit”,”age”:27}) //多条件 SQL中 AND操作
db.c.find({“$and”:{“username”:”vfeelit”,”age”:27}})

指定需返回的键

db.users.find({},{“username”:1,”email”:1})
db.users.find({},{“username”:1,”_id”:0})  //显式排除_id

由于_id总是返回,所以如果不需要看到这个字段,可以使用显式排除_id。

限制

2 查询条件
2.1 查询条件
比较操作符 $lt $lte $gt $gte(没有$eq)

db.users.find({“age”:{“$gte”:18,”$lte”:30}})
db.users.find({“registered”:{“$lt”:new Date(“01/01/2010”)}})
db.users.find({“username”:{“$ne”:”joe”}})

日期查询如何匹配一天 一周 或 一个月的数据? $ne操作符会进行全表扫描,慎用。

2.2 OR查询
有两种方式,使用$in 或 $or

db.orders.find({“ticket_no”:{“$in”:[12,13,15]}})
db.users.find({“user_id”:{“$in”:[123,’joe’]}) // 数组值类型可以不同

db.orders.find({“$or”:[{“ticket_no”:725},{“winner”:true}]})
db.orders.find({“$or”:[{“ticket_no”:{“$in”:[12,15,16]}}, {“winner”:true}]}) //混合

$in对应的是$nin,$nin操作符会进行全表扫描,慎用。$in能对单个字段进行过滤,如果要对多个字段进行过滤,就必须使用$or操作符。

2.3 $not

// id_num跟第一个值取模运输,返回1则匹配
db.users.find({“id_num”:{“$mod”:[5,1]}})

db.users.find({“id_num”:{“$not”:{“$mod”:[5,1]}}})

从内层往外叠加。

db.users.find(“age”:{“$lt”:30,”$gt”:20})  // 这个情况 默认为AND操作

#以下等同
db.users.find({“$and”:[{“x”:{“$lt”:1}},{“x”:4}]})
db.users.find({“x”:{“$lt”:1,”$in”:[4]}})

小于1 并且 等于4,在SQL中是矛盾的,但是在MongoDB中是合理的,因为字段可以是数组 或 文档,如果x的值是{“x”:[0,4]},以上查询就可以匹配。

3 特定类型的查询
3.1 null
null不仅会匹配某个键的值为null的文档,还会匹配不包括这个键的文档。如果仅想匹配键值为null的文档,既要检查该键是否是null,还要通过$exists条件判定键值是否存在:

db.c.find({“y”:null}) //不包含y键的文档也匹配
db.c.find({“y”:{“$in”:[null],”$exists”:true}})

注意这里引入的$in:[null],不能直接写成null,因为{}中必须对应的是键值对形式。而且不存在$eq这样的操作符。

3.2 正则表达式

db.users.find({“name”:/joe/i})
db.users.find({“name”:/joey?/i})

3.3 查询数组

{“fruit”:[“apple”,”banana”,”peach”]}
db.food.find({“fruit”:”banana”})

以上查询可以匹配,说明可以进入到数组内部。但是如果要匹配数据的两个以上的值,就需要改写一下。
1 $all

db.food.find({fruit:{“$all”:[“apple”,”banana”]}})

如果对只有一个元素的数组使用$all,就和不用$all一样。$all的意思是数组必须包含给出数组的全部值,顺序是无关重要的。要想查询数组特定位置的元素,需要使用key.index语法:

db.food.find({“fruit.2”:”peach”})

2 $size
$size可以用它查询特定长度的数组:

db.food.find({“fruit”:{“$size”:3}})

表示fruit的长度是3的文档被匹配。

3 $slice

> db.food.find()
{ "_id" : ObjectId("5544e88b627952fb8cc7251e"), "fruit" : [ "apple", "banana", "peach" ], "id" : 1 }
{ "_id" : ObjectId("5544e8a0627952fb8cc7251f"), "fruit" : [ "apple", "kumquat", "orange" ], "id" : 2 }
{ "_id" : ObjectId("5544e8b5627952fb8cc72520"), "fruit" : [ "cherry", "banana", "apple" ], "id" : 3 }
> db.food.find({},{fruit:{$slice:1}})
{ "_id" : ObjectId("5544e88b627952fb8cc7251e"), "fruit" : [ "apple" ], "id" : 1 }
{ "_id" : ObjectId("5544e8a0627952fb8cc7251f"), "fruit" : [ "apple" ], "id" : 2 }
{ "_id" : ObjectId("5544e8b5627952fb8cc72520"), "fruit" : [ "cherry" ], "id" : 3 }
> db.food.find({},{fruit:{$slice:2}})
{ "_id" : ObjectId("5544e88b627952fb8cc7251e"), "fruit" : [ "apple", "banana" ], "id" : 1 }
{ "_id" : ObjectId("5544e8a0627952fb8cc7251f"), "fruit" : [ "apple", "kumquat" ], "id" : 2 }
{ "_id" : ObjectId("5544e8b5627952fb8cc72520"), "fruit" : [ "cherry", "banana" ], "id" : 3 }
> db.food.find({},{fruit:{$slice:3}})
{ "_id" : ObjectId("5544e88b627952fb8cc7251e"), "fruit" : [ "apple", "banana", "peach" ], "id" : 1 }
{ "_id" : ObjectId("5544e8a0627952fb8cc7251f"), "fruit" : [ "apple", "kumquat", "orange" ], "id" : 2 }
{ "_id" : ObjectId("5544e8b5627952fb8cc72520"), "fruit" : [ "cherry", "banana", "apple" ], "id" : 3 }
> db.food.find({},{fruit:{$slice:[2,1]}})
{ "_id" : ObjectId("5544e88b627952fb8cc7251e"), "fruit" : [ "peach" ], "id" : 1 }
{ "_id" : ObjectId("5544e8a0627952fb8cc7251f"), "fruit" : [ "orange" ], "id" : 2 }
{ "_id" : ObjectId("5544e8b5627952fb8cc72520"), "fruit" : [ "apple" ], "id" : 3 } 

这个$slice理解起来比较麻烦,看以上例子。find的第一个参数是条件,第二参数是要返回的键,$slice可以用在这里控制返回的数组元素,{$slice:[2,1]}类似LIMIT 2,1。这个操作会返回所有键(属于一个奇葩操作)。

3.4 查询内嵌文档

4 $where查询
5 游标

while (cusor.hasNext()) {
    obj = cursor.next();
}

var cursor = db.people.find();
cursor.forEach(function(x) {
	print(x.name);
})

查询发往服务器,shell立刻获取前100个结果或前4MB数组(两者之中小者),这样下次调用next或者hasNext时就不必再次连接服务器取结果了。

5.1 limit skip 和 sort
sort类似SQL中的ORDER BY,可以按照多个字段进行排序:

db.c.find().sort({username:1,age:-1})

limit和skip类似SQL中limit操作

5.2 避免使用skip跳过大量结果
大结果集的分页问题的解决方案。

5.3 高级查询选项

db.foo.find()._addSpecial(“$maxscan”,20)

...

6 数据库命令
数据库命令是一种非常特殊的查询类型。

db.runCommand({“drop”:”test”});
db.runCommand({getLastError:1})

db.listCommands()

数据库命令总是返回一个包含“ok”键的文档。如果ok是1,说明命令执行成功了;如果是0,有一个额外的键errmsg说明命令失败的原因。

二 插入

> db.foo.insert({"name":"vfeelit"})
WriteResult({ "nInserted" : 1 })
> db.foo.find()
{ "_id" : ObjectId("5545743361557c6f4519300d"), "name" : "vfeelit" } 

insert操作会给文档自动增加一个“_id”键,它是一个ObjectId类型。

批量插入

db.foo.batchInsert([{“_id”:1},{“_id”:2},{“_id”:3}])

注意,MongoDB能接受的最大消息长度是48M。所以一次批量插入中能插入的文档是有限的。如果超过48M,多数驱动程序会将这个批量插入请求拆分。

批量插入中间有一个文档失败,前面的全部执行,后面的全部不执行。如果希望发送错误忽略而继续执行,可以使用驱动提供的continueOnError(shell中不支持)。

MongoDB只对数据进行最基本的检查:如果没有“_id”字段,就自动增加一个。所有文档都必须小于16MB(可以在shell中执行Object.bsonsize(doc)查看)

二 删除文档

db.foo.remove()
db.foo.remove({“username”:”vfeelit”})

这个remove跟SQL中的delete类似,它只是删除了数据。对应,也有一个drop操作,在SQL它会把表结构也删除,MongoDB中也类似,一般都不需要进行这个操作。

>for(var i = 1; i < 5000000; i++) { db.tester.insert({"foo":"bar","baz":i,"z":10-i})}
var timeRemove = function() {
	var s = (new Date()).getTime();
	db.tester.remove();
	db.findOne();
	var e = (new Date()).getTime() – s;
	print(“Time token: ”+e+”ms”);
}

timeRemove();

可以使用drop()替换上面的remove()来比较执行时间(drop()会快很多)。注:remove()可以指定条件进行部分删除。

三 更新文档
1 文档替换

var joe = db.users.findOne({“name”:”joe”});
joe.relationships = {“friends”:joe.friends,”enemies”:joe.enemies};
joe.username = joe.name;
delete joe.friends;
delete joe.enemies;
delete joe.name;
db.users.update({“name”:”joe”},joe)

以上的这个是先取记录然后修改记录,然后替换更新这个需要注意的是_id字段,它是唯一的。如果更新时的条件返回了多个文档,这个时候更新就会报错,因为试图用同样的_id去覆盖已经存在的多个文档。

2 使用修改器

db.analytics.update({“id”:1},{“$inc”:{“pageview”:1}})

$set修改器
$set用来指定一个字段的值。如果这个字段不存在,则创建它。

db.users.update({“name”:”joe”},{$set:{“favorite book”:”Green eggs”}})
db.users.update({“name”:”joe”},{$set:{“favorite book”:[”Green eggs”,”Foundation”]}})

db.users.update({“name”:”joe”},{$unset:{“favorite book”:1}}) //*****

#操作内嵌文档
db.blog.posts.update({“author.name”:”joe”},{$set:{“author.name”:”joe schmoe”}})

$inc修改器用来增加已有键的值,键不存在就创建一个。$inc和$set用法类似。它只能用于整数和浮点数,在其它类似数据上会导致操作失败。$inc键的值必须是数字。

db.blog.posts.update({“title”:”A blog post”},{$push:{“comments”: {“name”:”joe:}}})

#插入三条记录到数组
db.blog.posts.update({“id”:1},{$push:{“hourly”:{$each:[12,11,15]}}})

以下这个操作有点难理解,不过看起来还是比较重要的:

db.movies.update({“id”:100},{$push:{“top10”:{
	$each:[“11111”,”2222222”],
	$slice:-10
}}})

这里的$slice表示只保留最后的10项。

还可以排序:

db.movies.update({“id”:100},{“$push”:{
	$each:[{“name”:””,”rating”:6.6},{“name”:””,”rating”:4.3}],
	$slice:-10,
	$sort:{“rating”:-1}
}})

根据rating排序,保留最后10个。在$push中,$slice和$sort必须搭配$each使用。

将数组作为数据集合

db.users.update({“id”:100},{$addToSet:{“email”:”vfeelit@qq.com”}})

以上操作通过$push也可以实现,但是$addToSet可以保证插入的值不重复。结合$each可以插入多个不重复值:

db.users.update({“id”:100},{
$addToSet:{
“email”:{
$each:[‘vfeelit@qq.com’,”ifeeline@qq.com”]
}
}
});

删除元素

##删除匹配
db.list.update({},{“$pull”:{“todo”:”laundry”}})

##删除头尾
db.list.update({},{$pop:{“todo”:1}})
db.list.update({},{$pop:{“todo”:-1}})

修改数组
可以通过指定下标来更新具体的值。MongoDB提供了$定位符,用来定位查询文档已经匹配的数组元素并进行更新。

db.blog.update({“comments.author”:”John”},{$set:{“comments.$.author”:”jim”}})

注意:定位符只更新第一个匹配的元素。

upset
update()的第三个参数控制更是是否是upset更新(默认为false),这个更新的特点是存在则更新,不存在则插入。

db.analytics.update({“url”:”/blog”},{“$inc”:{“pageview”:1}},true)

更新多个文档
update()的第四个参数控制是否可以更新多个文档(默认为false,如果条件匹配多个文档,也只更新第一个)

db.users.update({“id”:{$gt:10}},{“$set”:{“gift”:”Hello”}},false,true)

返回被更新的文档
调用getLastError能获取关于更新的有限信息。

ps = db.runCommand({“findAndModify”:”processes”,
	“query”:{“status”:”READY”},
	“sort”:{“priority”:-1},
	“update”:{
		“$set”:{“status”:”RUNNING”}
}
});

##返回
{
	“ok”:1,
	“value”:{
		“_id”:,
		“priority”:1,
		“status”:”READY”
}
}

findAndModify返回的是修改前的文档。注意看返回的结果,这个文档使用键value来保存。

MongoDB SHELL使用

MongoDB提供的SHELL是一个Javascript Shell,实际想象一下MySQL的Shell,它可以认为是一个SQL Shell,可以执行SQL语句,Javascript Shell自然可以执行Javascript脚本。

启动Shell:

mongo
mongo 192.168.1.168:9999/vdb
mongo --host 192.168.1.168 –u admin –p 123456 –authenticationDatabase vdb

注意,如果不指定数据库,那么默认Shell会链接MongoDB服务器的test数据库,并将数据库链接赋值给全局变量db。这个变量是通过shell访问MongoDB的主要入口点。

如下:

###终端可用命令
> help
	db.help()                    help on db methods
	db.mycoll.help()             help on collection methods
	sh.help()                    sharding helpers
	rs.help()                    replica set helpers
	help admin                   administrative help
	help connect                 connecting to a db help
	help keys                    key shortcuts
	help misc                    misc things to know
	help mr                      mapreduce

	show dbs                     show database names
	show collections             show collections in current database
	show users                   show users in current database
	show profile                 show most recent system.profile entries with time >= 1ms
	show logs                    show the accessible logger names
	show log [name]              prints out the last segment of log in memory, 'global' is default
	use <db_name>                set current database
	db.foo.find()                list objects in collection foo
	db.foo.find( { a : 1 } )     list objects in foo where a == 1
	it                           result of the last line evaluated; use to further iterate
	DBQuery.shellBatchSize = x   set default number of items to display on shell
	exit                         quit the mongo shell

针对数据库 和 数据集合的可以用操作

> db.help()
DB methods:
	db.adminCommand(nameOrDocument) - switches to 'admin' db, and runs command [ j
	db.auth(username, password)
	db.cloneDatabase(fromhost)
	db.commandHelp(name) returns the help for the command
	db.copyDatabase(fromdb, todb, fromhost)
	db.createCollection(name, { size : ..., capped : ..., max : ... } )
	db.createUser(userDocument)
	db.currentOp() displays currently executing operations in the db
	db.dropDatabase()
	db.eval(func, args) run code server-side
	db.fsyncLock() flush data to disk and lock server for backups
	db.fsyncUnlock() unlocks server following a db.fsyncLock()
	db.getCollection(cname) same as db['cname'] or db.cname
	db.getCollectionInfos()
	db.getCollectionNames()
	db.getLastError() - just returns the err msg string
	db.getLastErrorObj() - return full status object
	db.getLogComponents()
	db.getMongo() get the server connection object
	db.getMongo().setSlaveOk() allow queries on a replication slave server
	db.getName()
	db.getPrevError()
	db.getProfilingLevel() - deprecated
	db.getProfilingStatus() - returns if profiling is on and slow threshold
	db.getReplicationInfo()
	db.getSiblingDB(name) get the db at the same server as this one
	db.getWriteConcern() - returns the write concern used for any operations on th
	db.hostInfo() get details about the server's host
	db.isMaster() check replica primary status
	db.killOp(opid) kills the current operation in the db
	db.listCommands() lists all the db commands
	db.loadServerScripts() loads all the scripts in db.system.js
	db.logout()
	db.printCollectionStats()
	db.printReplicationInfo()
	db.printShardingStatus()
	db.printSlaveReplicationInfo()
	db.dropUser(username)
	db.repairDatabase()
	db.resetError()
	db.runCommand(cmdObj) run a database command.  if cmdObj is a string, turns it
	db.serverStatus()
	db.setLogLevel(level,<component>)
	db.setProfilingLevel(level,<slowms>) 0=off 1=slow 2=all
	db.setWriteConcern( <write concern doc> ) - sets the write concern for writes 
	db.unsetWriteConcern( <write concern doc> ) - unsets the write concern for wri
	db.setVerboseShell(flag) display extra information in shell output
	db.shutdownServer()
	db.stats()
	db.version() current version of the server

> db.test.help()
DBCollection help
	db.test.find().help() - show DBCursor help
	db.test.count()
	db.test.copyTo(newColl) - duplicates collection by copying all documents to newColl; no indexes are copied.
	db.test.convertToCapped(maxBytes) - calls {convertToCapped:'test', size:maxBytes}} command
	db.test.dataSize()
	db.test.distinct( key ) - e.g. db.test.distinct( 'x' )
	db.test.drop() drop the collection
	db.test.dropIndex(index) - e.g. db.test.dropIndex( "indexName" ) or db.test.dropIndex( { "indexKey" : 1 } )
	db.test.dropIndexes()
	db.test.ensureIndex(keypattern[,options])
	db.test.explain().help() - show explain help
	db.test.reIndex()
	db.test.find([query],[fields]) - query is an optional query filter. fields is optional set of fields to return.
	                                              e.g. db.test.find( {x:77} , {name:1, x:1} )
	db.test.find(...).count()
	db.test.find(...).limit(n)
	db.test.find(...).skip(n)
	db.test.find(...).sort(...)
	db.test.findOne([query])
	db.test.findAndModify( { update : ... , remove : bool [, query: {}, sort: {}, 'new': false] } )
	db.test.getDB() get DB object associated with collection
	db.test.getPlanCache() get query plan cache associated with collection
	db.test.getIndexes()
	db.test.group( { key : ..., initial: ..., reduce : ...[, cond: ...] } )
	db.test.insert(obj)
	db.test.mapReduce( mapFunction , reduceFunction , <optional params> )
	db.test.aggregate( [pipeline], <optional params> ) - performs an aggregation on a collection; returns a cursor
	db.test.remove(query)
	db.test.renameCollection( newName , <dropTarget> ) renames the collection.
	db.test.runCommand( name , <options> ) runs a db command with the given name where the first param is the collection name
	db.test.save(obj)
	db.test.stats({scale: N, indexDetails: true/false, indexDetailsKey: <index key>, indexDetailsName: <index name>})
	db.test.storageSize() - includes free space allocated to this collection
	db.test.totalIndexSize() - size in bytes of all the indexes
	db.test.totalSize() - storage allocated for all data and indexes
	db.test.update(query, object[, upsert_bool, multi_bool]) - instead of two flags, you can pass an object with fields: upsert, multi
	db.test.validate( <full> ) - SLOW
	db.test.getShardVersion() - only for use with sharding
	db.test.getShardDistribution() - prints statistics about data distribution in the cluster
	db.test.getSplitKeysForChunks( <maxChunkSize> ) - calculates split points over all chunks and returns splitter function
	db.test.getWriteConcern() - returns the write concern used for any operations on this collection, inherited from server/db if set
	db.test.setWriteConcern( <write concern doc> ) - sets the write concern for writes to the collection
	db.test.unsetWriteConcern( <write concern doc> ) - unsets the write concern for writes to the collection

Mongo SHELL 和 数据库 和 数据集合对应的原型是Mongo 和 DB 和 DBCollection:

> Mongo
function Mongo() { [native code] }
> DB
function DB() { [native code] }
> DBCollection
function DBCollection() { [native code] } 

根据Javascript的特征,如果我们要屏蔽某些方法,只要通过它的prototype来操作即可(这里的DB和db实际是类和类对象的关系):

var no = function(){};
db.dropDatabase = DB.prototype.dropDatabase = no;
DBCollection.prototype.drop = no;
DBCollection.prototype.dropIndex = no;

通过db.getCollection(cname) or db[‘cname’] or db.cname获取集合时,实际是一个DBCollection的类对象,所以在之前更改了原型,这个后生成的对象的某些方法就不能使用。

对比PHP链接MongoDB的代码:

$client = new MongoClient();				//Mongo 连接器
$db = $client->selectDB(“test”);		//DB

$collection = $db->selectCollection(“vvv”); //DBCollection

$collection->find();

第一步类似打开SHELL(指定主机等), 第二步类似SHELL中的选择数据库被赋值给db,第三步类似db.getCollection(cname)。大概可以看出,PHP驱动提供的名称与操作方法基本类似。

SHELL操作:

> db
test
> show dbs
comedy  0.031GB
local   0.031GB
test    0.031GB
> use comedy
switched to db comedy
> db
comedy
> show collections
blog
system.indexes
> db.blog.find()
{ "_id" : ObjectId("55442c13fe840f662522570b"), "id" : 1, "title" : "MongoDB Begin", "content" : "-----" }

由于Mongo SHELL也是一个JS解析器,可以加载外部的JS文件执行:

load(“jscrip.js”)

需要知道,除了Mongo SHELL引入的新内容外,JS语言的东西都可以直接运行,比如上面的load()就是一个本地函数。

MongoDB 安装日志

当前MogonDB主版本3.x,官方提供的安装源从这个版本开始进行了重新的组织。

1 首先添加yum源:

#3.0版本,以下的$releasever替换成5Server或6Server或7Server
[mongodb-org-3.0]
name=MongoDB Repository
baseurl=http://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.0/x86_64/
gpgcheck=0
enabled=1

#2.x版本
[mongodb-org-2.6]
name=MongoDB 2.6 Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1

2 安装:

#安装最新版本(yum源的最新版本,这里是3.0)
yum install -y mongodb-org

#以下程序包被安装
# mongodb-org
# mongodb-org-mongos
# mongodb-org-server
# mongodb-org-shell
# mongodb-org-tools

如果要指定安装某个版本,则需要指定:

yum install -y mongodb-org-3.0.2 mongodb-org-server-3.0.2 mongodb-org-shell-3.0.2 mongodb-org-mongos-3.0.2 mongodb-org-tools-3.0.2

为了防止意外的升级到最新版本,可以做如下设置:

vi /etc/yum.conf
exclude=mongodb-org,mongodb-org-server,mongodb-org-shell,mongodb-org-mongos,mongodb-org-tools

检测安装:

rpm -qa | grep mongo
mongodb-org-shell-3.0.2-1.el6.x86_64
mongodb-org-3.0.2-1.el6.x86_64
mongodb-org-mongos-3.0.2-1.el6.x86_64
mongodb-org-server-3.0.2-1.el6.x86_64
mongodb-org-tools-3.0.2-1.el6.x86_64

##客户端
rpm -ql mongodb-org-shell-3.0.2-1.el6.x86_64
/usr/bin/mongo  #mongo启动Mongodb Shell
/usr/share/man/man1/mongo.1

rpm -ql mongodb-org-3.0.2-1.el6.x86_64
(contains no files)

rpm -ql mongodb-org-mongos-3.0.2-1.el6.x86_64
/usr/bin/mongos	####
/usr/share/man/man1/mongos.1

##服务端
rpm -ql mongodb-org-server-3.0.2-1.el6.x86_64
/etc/init.d/mongod	#MongoDB启动脚本
/etc/mongod.conf	#MongoDB配置文件
/etc/sysconfig/mongod
/usr/bin/mongod		#MongoDB主进程
/usr/share/doc/*
/usr/share/man/man1/mongod.1
/var/lib/mongo
/var/log/mongodb
/var/log/mongodb/mongod.log #MongoDB日志
/var/run/mongodb

##工具
rpm -ql mongodb-org-tools-3.0.2-1.el6.x86_64
/usr/bin/bsondump
/usr/bin/mongodump
/usr/bin/mongoexport
/usr/bin/mongofiles
/usr/bin/mongoimport
/usr/bin/mongooplog
/usr/bin/mongoperf
/usr/bin/mongorestore
/usr/bin/mongostat
/usr/bin/mongotop
/usr/share/man/*

注:这个结构跟MySQL非常类似,比如mysql启动客户端工具,mysqld是服务端进程,MySQL本身也提供了一些列的工具。

3 运行
为了能正确启动MongoDB,需要修改/etc/selinux.conf,把SELINUX=设置为permissive或disabled。

默认安装完毕就可以直接启动:

service mongodb start

以下是启动时的日志,参考:

CONTROL  ***** SERVER RESTARTED *****
JOURNAL  [initandlisten] journal dir=/var/lib/mongo/journal
JOURNAL  [initandlisten] recover : no journal files present, no recovery needed
JOURNAL  [initandlisten] preallocateIsFaster=true 2.82
JOURNAL  [initandlisten] preallocateIsFaster=true 2.14
JOURNAL  [initandlisten] preallocateIsFaster=true 2.32
JOURNAL  [initandlisten] preallocating a journal file /var/lib/mongo/journal/prealloc.0
JOURNAL  [initandlisten] preallocating a journal file /var/lib/mongo/journal/prealloc.1
-        [initandlisten]   File Preallocator Progress: 115343360/134217728 85%
JOURNAL  [initandlisten] preallocating a journal file /var/lib/mongo/journal/prealloc.2
-        [initandlisten]   File Preallocator Progress: 115343360/134217728 85%
JOURNAL  [durability] Durability thread started
JOURNAL  [journal writer] Journal writer thread started
CONTROL  [initandlisten] MongoDB starting : pid=16474 port=27017 dbpath=/var/lib/mongo 64-bit host=vfeelit
CONTROL  [initandlisten] 
CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
CONTROL  [initandlisten] **        We suggest setting it to 'never'
CONTROL  [initandlisten] 
CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
CONTROL  [initandlisten] **        We suggest setting it to 'never'
CONTROL  [initandlisten] 
CONTROL  [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 1024 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files.
CONTROL  [initandlisten] 
CONTROL  [initandlisten] db version v3.0.2
CONTROL  [initandlisten] git version: 6201872043ecbbc0a4cc169b5482dcf385fc464f
CONTROL  [initandlisten] OpenSSL version: OpenSSL 1.0.1e-fips 11 Feb 2013
CONTROL  [initandlisten] build info: Linux ip-10-171-120-213 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011 x86_64 BOOST_LIB_VERSION=1_49
CONTROL  [initandlisten] allocator: tcmalloc
CONTROL  [initandlisten] options: { config: "/etc/mongod.conf", net: { bindIp: "127.0.0.1" }, processManagement: { fork: true, pidFilePath: "/var/run/mongodb/mongod.pid" }, storage: { dbPath: "/var/lib/mongo", mmapv1: { smallFiles: true } }, systemLog: { destination: "file", logAppend: true, path: "/var/log/mongodb/mongod.log" } }
INDEX    [initandlisten] allocating new ns file /var/lib/mongo/local.ns, filling with zeroes...
STORAGE  [FileAllocator] allocating new datafile /var/lib/mongo/local.0, filling with zeroes...
STORAGE  [FileAllocator] creating directory /var/lib/mongo/_tmp
STORAGE  [FileAllocator] done allocating datafile /var/lib/mongo/local.0, size: 16MB,  took 0.06 secs
NETWORK  [initandlisten] waiting for connections on port 27017


4 安装驱动(PHP)

MongoDB提供了很多语言的驱动,以下是安装PHP驱动:

wget http://pecl.php.net/get/mongo-1.6.7.tgz
tar zxvf mongo-1.6.7.tgz
cd mongo-1.6.7
./configure --with-php-config=/usr/local/php-5.5.15/bin/php-config
make && make install

vi /usr/local/php-5.5.15/etc/php.ini
extension = "mongo.so"

以上这个是原生的针对PHP的添加对MongoDB支持的扩展。PHP里面还有一个是对MongoDB驱动C库的包装器。参考:http://pecl.php.net/package/mongodb。

永久链接:http://blog.ifeeline.com/1612.html