一、安裝MongoDB
1、安裝MongoDB
rpm包下載地址:http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/RPMS/
[[email protected] ~]# yum localinstall -y mongo-10gen-2.4.14-mongodb_1.x86_64.rpm mongo-10gen-server-2.4.14-mongodb_1.x86_64.rpm
2、查看rpm包生成的幾個重要文件
[[email protected] ~]# rpm -ql mongo-10gen /usr/bin/bsondump /usr/bin/mongo /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 [[email protected] ~]# rpm -ql mongo-10gen-server /etc/mongod.conf /etc/rc.d/init.d/mongod /etc/sysconfig/mongod /usr/bin/mongod /usr/bin/mongos /usr/share/man/man1/mongod.1 /usr/share/man/man1/mongos.1 /var/lib/mongo /var/log/mongo /var/log/mongo/mongod.log
3、初始化數據庫
說明:實際使用中將存放數據的目錄放在有冗餘的邏輯捲上。
[[email protected] ~]# mkdir /data/mongodb -p [[email protected] ~]# vim /etc/mongod.conf dbpath=/data/mongodb
4、啓動數據庫
[[email protected] ~]# service mongod start Starting mongod: about to fork child process, waiting until server is ready for connections. forked process: 4713 all output going to: /var/log/mongo/mongod.log child process started successfully, parent exiting [確定] [[email protected] ~]# ss -tnlp |grep mongod LISTEN 0 128 *:28017 *:* users:(("mongod",4713,11)) LISTEN 0 128 *:27017 *:* users:(("mongod",4713,9))
5、MongoDB的web接口
二、使用MongoDB
1、MongoDB與MySQL語法對比
傳統的關係數據庫一般由數據庫(database)、表(table)、記錄(record)三個層次概念組成,MongoDB是由數據庫(database)、集合(collection)、文檔對象(document)三個層次組成。MongoDB對於關係型數據庫裏的表,但是集合中沒有列、行和關係概念,這體現了模式自由的特點。
2、mongodb語法
查詢colls所有數據
db.colls.find() //select * from colls
通過指定條件查詢
db.colls.find({‘last_name’: ‘Smith’});//select * from colls where last_name=’Smith’
指定多條件查詢
db.colls.find( { x : 3, y : “foo” } );//select * from colls where x=3 and y=’foo’
指定條件範圍查詢
db.colls.find({j: {$ne: 3}, k: {$gt: 10} });//select * from colls where j!=3 and k>10
查詢不包括某內容
db.colls.find({}, {a:0});//查詢除a爲0外的所有數據
支持<, <=, >, >=查詢,需用符號替代分別爲$lt,$lte,$gt,$gte
db.colls.find({ “field” : { $gt: value } } ); db.colls.find({ “field” : { $lt: value } } ); db.colls.find({ “field” : { $gte: value } } ); db.colls.find({ “field” : { $lte: value } } );
也可對某一字段做範圍查詢
db.colls.find({ “field” : { $gt: value1, $lt: value2 } } );
不等於查詢用字符$ne
db.colls.find( { x : { $ne : 3 } } );
in查詢用字符$in
db.colls.find( { “field” : { $in : array } } ); db.colls.find({j:{$in: [2,4,6]}});
not in查詢用字符$nin
db.colls.find({j:{$nin: [2,4,6]}});
取模查詢用字符$mod
db.colls.find( { a : { $mod : [ 10 , 1 ] } } )// where a % 10 == 1
$all查詢
db.colls.find( { a: { $all: [ 2, 3 ] } } );//指定a滿足數組中任意值時
$size查詢
db.colls.find( { a : { $size: 1 } } );//對對象的數量查詢,此查詢查詢a的子對象數目爲1的記錄
$exists查詢
db.colls.find( { a : { $exists : true } } ); // 存在a對象的數據 db.colls.find( { a : { $exists : false } } ); // 不存在a對象的數據
$type查詢$type值爲bsonhttp://bsonspec.org/數 據的類型值
db.colls.find( { a : { $type : 2 } } ); // 匹配a爲string類型數據 db.colls.find( { a : { $type : 16 } } ); // 匹配a爲int類型數據
使用正則表達式匹配
db.colls.find( { name : /acme.*corp/i } );//類似於SQL中like
內嵌對象查詢
db.colls.find( { “author.name” : “joe” } );
1.3.3版本及更高版本包含$not查詢
db.colls.find( { name : { $not : /acme.*corp/i } } ); db.colls.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );
sort()排序
db.colls.find().sort( { ts : -1 } );//1爲升序2爲降序
limit()對限制查詢數據返回個數
db.colls.find().limit(10)
skip()跳過某些數據
db.colls.find().skip(10)
snapshot()快照保證沒有重複數據返回或對象丟失
count()統計查詢對象個數
db.students.find({‘address.state’ : ‘CA’}).count();//效率較高 db.students.find({‘address.state’ : ‘CA’}).toArray().length;//效率很低
group()對查詢結果分組和SQL中group by函數類似
distinct()返回不重複值
3、查詢語句說明:
“db.collection.find(<query>,<projection>)”
類似於SQL中select語句,其中<query>相當於where子句,而<projection>相當於要選定的字段。
如果使用的find()方法中不包含<query>,則意味着要返回對應collection的所有文檔。
“db.collection.count()”方法可以統計指定collection中文檔的個數。
比較運算:
$gt:挑選指定字段值大於指定值的文檔,語法格式“{field: {$gt: value}}”;
$gte:挑選指定字段值大於等於指定值的文檔,語法格式“{field: $gte: value}”;
$in:挑選指定字段的值位於指定數組中的文檔,語法格式“{filed: {$in: [<value1>,<value2>,...<valueN>]}}”;
$lt:挑選指定字段值小於指定值的文檔,語法格式“{field: {$lt: value}}”;
$lte:挑選指定字段值小於等於指定值的文檔,語法格式“{field: {$lte: value}}”;
$ne:挑選指定字段值不等於指定值的文檔,語法格式“{filed: {$ne: value}}”;
$nin:挑選指定字段的值沒有位於指定數組中或不存在的文檔,語法格式“{filed: {$nin: [<value1>,<value2>...valueN]}}”;
邏輯運算:
邏輯運算一般用於連接多個選擇條件,MongoDB支持的邏輯運算“Query Selector”有以下幾種:
$or:或運算,語句格式“{$or: [{<expression1>},{<expression2>},... ,{<expressionN>}]}”
$and:與運算,語法格式“{$and: [{<expression1>},{<expression2>},... ,{<expressionN>}]}”
$and:非運算,語法格式“{field: {$not: {<operator expression>}}}”
$nor:反運算,即返回不符合所有指定條件的文檔,語法格式“$nor: [{<expression1>},{<expression2>},.... ,{<expressionN>}]}”
元素查詢:
如果要根據文檔中是否存在某字段等條件來挑選文檔,則需要用到元素運算。
$exixts:根據指定字段的存在性挑選文檔,語法格式“{ field: {$exists: <boolean>}}”,指定<boolean>的值爲“true”則返回存在指定字段的文檔,“false”則返回不存在指定字段的文檔。
$mod:將指定字段的值進行取模運算,並返回其餘數爲指定值的文檔,語法格式“{field: {$mod: [divisor, remainder]}}”。
$type:返回指定字段的值類型爲指定類型的文檔,語法格式“{field: {$type: <BSON type>}}”。
3、實際練習
連入數據庫
[[email protected] ~]# mongo MongoDB shell version: 2.4.14 connecting to: test Welcome to the MongoDB shell. For interactive help, type "help". For more comprehensive documentation, see http://docs.mongodb.org/ Questions? Try the support group http://groups.google.com/group/mongodb-user >
數據的插入
> show dbs admin(empty) local0.078125GB > db.testcoll.insert({Name:"bols"}) > show collections system.indexes testcoll > db.testcoll.insert({Name:"longls"}) > db.testcoll.find() { "_id" : ObjectId("5602a24111db41a96277c761"), "Name" : "bols" } { "_id" : ObjectId("5602a28811db41a96277c762"), "Name" : "longls" } > show dbs admin(empty) local0.078125GB test0.203125GB
查看狀態:
> db.testcoll.stats() { "ns" : "test.testcoll", "count" : 2, "size" : 80, "avgObjSize" : 40, "storageSize" : 4096, "numExtents" : 1, "nindexes" : 1, "lastExtentSize" : 4096, "paddingFactor" : 1, "systemFlags" : 1, "userFlags" : 0, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1 }
就插入了兩條數據而佔用了100多M的空間,說明很佔用存儲空間。
mongodb佔用空間過大的原因,在官方的FAQ中,提到有如下幾個方面:
空間的預分配:爲避免形成過多的硬盤碎片,mongodb每次空間不足時都會申請生成一大塊的硬盤空間,而且申請的量從64M、128M、 256M那樣的指數遞增,直到2G爲單個文件的最大體積。隨着數據量的增加,你可以在其數據目錄裏看到這些整塊生成容量不斷遞增的文件。
字段名所佔用的空間:爲了保持每個記錄內的結構信息用於查詢,mongodb需要把每個字段的key-value都以BSON的形式存儲,如果 value域相對於key域並不大,比如存放數值型的數據,則數據的overhead是最大的。一種減少空間佔用的方法是把字段名儘量取短一些,這樣佔用 空間就小了,但這就要求在易讀性與空間佔用上作爲權衡了。我曾建議作者把字段名作個index,每個字段名用一個字節表示,這樣就不用擔心字段名取多長 了。但作者的擔憂也不無道理,這種索引方式需要每次查詢得到結果後把索引值跟原值作一個替換,再發送到客戶端,這個替換也是挺耗費時間的。現在的實現算是 拿空間來換取時間吧。
刪除記錄不釋放空間:這很容易理解,爲避免記錄刪除後的數據的大規模挪動,原記錄空間不刪除,只標記“已刪除”即可,以後還可以重複利用。
可以定期運行db.repairDatabase()來整理記錄,但這個過程會比較緩慢。
刪除collections:
> db.testcoll.drop() true > show collections system.indexes > show dbs admin(empty) local0.078125GB test0.203125GB
添加練習例子:
> for(i=1;i<=100;i++) db.testcoll.insert({Name:"User:"+i,Age:i,Gender:"F",PreferBooks:["First blood","Second blood"]})
查看前兩行文檔:
> db.testcoll.find().limit(2) { "_id" : ObjectId("5602aa5311db41a96277c763"), "Name" : "User:1", "Age" : 1, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c764"), "Name" : "User:2", "Age" : 2, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] }
刪除年齡爲5的文檔:
> db.testcoll.remove({Age:5}) > db.testcoll.find().limit(6) { "_id" : ObjectId("5602aa5311db41a96277c763"), "Name" : "User:1", "Age" : 1, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c764"), "Name" : "User:2", "Age" : 2, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c765"), "Name" : "User:3", "Age" : 3, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c766"), "Name" : "User:4", "Age" : 4, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c768"), "Name" : "User:6", "Age" : 6, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c769"), "Name" : "User:7", "Age" : 7, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] }
刪除用戶爲User:3的文檔:
> db.testcoll.remove({Name: "User:3"}) > db.testcoll.find().limit(5) { "_id" : ObjectId("5602aa5311db41a96277c763"), "Name" : "User:1", "Age" : 1, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c764"), "Name" : "User:2", "Age" : 2, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c766"), "Name" : "User:4", "Age" : 4, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c768"), "Name" : "User:6", "Age" : 6, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c769"), "Name" : "User:7", "Age" : 7, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] }
將User:4用戶的年齡改爲22:
> db.testcoll.update({Name: "User:4"},{$set: {Age: 22}}) > db.testcoll.find().limit(4) { "_id" : ObjectId("5602aa5311db41a96277c763"), "Name" : "User:1", "Age" : 1, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c764"), "Name" : "User:2", "Age" : 2, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c766"), "Name" : "User:4", "Age" : 22, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c768"), "Name" : "User:6", "Age" : 6, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] }
查看test庫的文檔數,及年齡大於97的文檔:
> db.testcoll.count() 98 > db.testcoll.find({Age: {$gte :97}}) { "_id" : ObjectId("5602aa5311db41a96277c7c3"), "Name" : "User:97", "Age" : 97, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c7c4"), "Name" : "User:98", "Age" : 98, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c7c5"), "Name" : "User:99", "Age" : 99, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c7c6"), "Name" : "User:100", "Age" : 100, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] }
查詢年齡大於97的文檔並只顯示Name和Age:
> db.testcoll.find({Age: {$gte :97}},{Name:1,Age:1}) { "_id" : ObjectId("5602aa5311db41a96277c7c3"), "Name" : "User:97", "Age" : 97 } { "_id" : ObjectId("5602aa5311db41a96277c7c4"), "Name" : "User:98", "Age" : 98 } { "_id" : ObjectId("5602aa5311db41a96277c7c5"), "Name" : "User:99", "Age" : 99 } { "_id" : ObjectId("5602aa5311db41a96277c7c6"), "Name" : "User:100", "Age" : 100 }
查詢Age大於60並小於66的文檔:
> db.testcoll.find({$and:[{Age: {$gt:60}},{Age: {$lt: 66}}]},{Name:1}) { "_id" : ObjectId("5602aa5311db41a96277c79f"), "Name" : "User:61" } { "_id" : ObjectId("5602aa5311db41a96277c7a0"), "Name" : "User:62" } { "_id" : ObjectId("5602aa5311db41a96277c7a1"), "Name" : "User:63" } { "_id" : ObjectId("5602aa5311db41a96277c7a2"), "Name" : "User:64" } { "_id" : ObjectId("5602aa5311db41a96277c7a3"), "Name" : "User:65" }
查詢包含Adress字段的文檔:
> db.testcoll.find({Adress: {$exists:true}}) { "_id" : ObjectId("5602b12411db41a96277c7c8"), "Name" : "xiyan", "Age" : 25, "Gender" : "F", "Adress" : "Chongqing,China" }
將Age大於98文檔中的Gender改爲M:
> db.testcoll.update({Age: {$gt:98}},{$set: {Gender: "M"}},{multi:true}) > db.testcoll.find({Age: {$gte: 98}}) { "_id" : ObjectId("5602aa5311db41a96277c7c4"), "Name" : "User:98", "Age" : 98, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c7c5"), "Name" : "User:99", "Age" : 99, "Gender" : "M", "PreferBooks" : [ "First blood", "Second blood" ] } { "_id" : ObjectId("5602aa5311db41a96277c7c6"), "Name" : "User:100", "Age" : 100, "Gender" : "M", "PreferBooks" : [ "First blood", "Second blood" ] }
將Name爲User:99的文檔中PreferBooks項給刪除:
> db.testcoll.update({Name: "User:99"},{$unset: {PreferBooks: ""}}) > db.testcoll.find({Age: {$gte: 98}}) { "_id" : ObjectId("5602aa5311db41a96277c7c4"), "Name" : "User:98", "Age" : 98, "Gender" : "F", "PreferBooks" : [ "First blood", "Second blood" ] } { "Age" : 99, "Gender" : "M", "Name" : "User:99", "_id" : ObjectId("5602aa5311db41a96277c7c5") } { "_id" : ObjectId("5602aa5311db41a96277c7c6"), "Name" : "User:100", "Age" : 100, "Gender" : "M", "PreferBooks" : [ "First blood", "Second blood" ] }