1.安裝mongodb nodejs driver
要安裝mongodb nodejs的原生driver,可以通過(guò)npm,也可以通過(guò)github下載:
npm install mongodb
2連接到數(shù)據(jù)庫(kù)
var mongo = require('mongodb'),
Server = mongo.Server,
Db = mongo.Db;
var server = new Server('localhost', 27017, {auto_reconnect: true});
var db = new Db('foo', server);
db.open(function(err, db) {
if(!err) {
console.log("We are connected");
}
});
查詢Get
db.open(function(err, db) {
if(!err) {
console.log("We are connected");
db.collection('bar', function(err, collection){
collection.find().toArray(function(error, bars){console.log(bars);});
collection.find({a:1}).toArray(function(error, bars){console.log(bars);});
collection.findOne({a: 1}, function(error, bar){console.log(bar)});
});
}
});
這里一旦用find獲取到結(jié)果集之后,需要調(diào)用toArray方法,并傳遞回調(diào)函數(shù),這個(gè)時(shí)候才能拿到真正的數(shù)據(jù)。第二個(gè)find語(yǔ)句則是查找所有a=1的文檔。第三個(gè)find語(yǔ)句則是只找第一個(gè)滿足條件的文檔。具體更多的過(guò)濾條件可以參考官方的Query語(yǔ)句。這里有個(gè)有趣的事情需要注意,find本身并不執(zhí)行查詢,它只是返回一個(gè)Cursor實(shí)例,你可以遍歷這個(gè)Cursor來(lái)查詢數(shù)據(jù)。如下面的例子:
// Cursors don't run their queries until you actually attempt to retrieve data
// from them.
// Find returns a Cursor, which is Enumerable. You can iterate:
collection.find(function(err, cursor) {
cursor.each(function(err, item) {
if(item != null) console.dir(item);
});
});
// You can turn it into an array
collection.find(function(err, cursor) {
cursor.toArray(function(err, items) {
console.log("count: " + items.length);
});
});
插入Insert
db.open(function(err, db) {
if(!err) {
db.collection('bar', function(err, collection) {
var doc1 = {a: 1};
var doc2 = {a: 2, b: 'b2'};
var docs = [{a:3}, {a:4}];
collection.insert(doc1);
collection.insert(doc2, {safe:true}, function(err, result) {});
collection.insert(docs, {safe:true}, function(err, result) {});
});
}
});
第一個(gè)insert和第二個(gè)insert的區(qū)別在于,增加了一個(gè)option對(duì)象參數(shù)({safe:true})以及一個(gè)回調(diào)函數(shù)。MongoDB的
insert/update/remove都是異步的,也就是說(shuō)發(fā)出insert命令之后,就不管數(shù)據(jù)庫(kù)是否執(zhí)行成功了。要想知道數(shù)據(jù)庫(kù)是否執(zhí)行成功,需
要再發(fā)出一個(gè)查詢請(qǐng)求來(lái)獲取連接(Connection)的最后一個(gè)錯(cuò)誤狀態(tài)。為了簡(jiǎn)化這個(gè)過(guò)程,也就支持{safe:true}這個(gè)參數(shù),使得
insert和錯(cuò)誤狀態(tài)查詢能夠一起執(zhí)行,一旦設(shè)置這個(gè)參數(shù),一定要增加回調(diào)函數(shù)作為第三個(gè)參數(shù)。具體地,我們可以看下面地例子來(lái)理解這個(gè)
{safe:true}的意義:
db.collection('bar', function(err, collection){
collection.insert({a:996, _id:'1'}, function(error, bars){
console.log('insert success without safe');
console.log(error);
console.log(bars);
collection.insert({a:996, _id:'1'}, {safe:true}, function(error, bars){
console.log('insert fail with safe and get error');
console.log(error);
console.log(bars);
collection.insert({a:996, _id:'1'}, function(error, bars){
console.log('insert fail without safe but no error');
console.log(error);
console.log(bars);
});
});
});
});
# output result
[app.js] insert success without safe
[app.js] null
[app.js] [ { a: 996, _id: '1' } ]
[app.js] insert fail with safe and get error
[app.js] { [MongoError: E11000 duplicate key error index: foo.bar.$_id_? dup key: { : "1" }]
name: 'MongoError',
err: 'E11000 duplicate key error index: foo.bar.$_id_? dup key: { : "1" }',
code: 11000,
n: 0,
connectionId: 38,
ok: 1 }
[app.js] undefined
[app.js] insert fail without safe but no error
[app.js] null
[app.js] [ { a: 996, _id: '1' } ]
這里的_id是mongodb默認(rèn)的主鍵,是不允許重復(fù)的。如果你傳入了_id則以傳入的值作為主鍵,如果沒(méi)有傳入則會(huì)自動(dòng)生成。你可以看到,第一次insert,我們也不關(guān)心是不是真的插入了,幸運(yùn)的是真的成功了,因?yàn)椴淮嬖赺id為1的數(shù)據(jù)。第二次插入的時(shí)候,我們?cè)O(shè)置{safe:true}以確保一定插入成功,這是會(huì)報(bào)主鍵重復(fù)的錯(cuò)誤。第三次同樣的插入,但是不設(shè)置{safe:true},這個(gè)時(shí)候發(fā)現(xiàn)并沒(méi)有報(bào)錯(cuò),而且回調(diào)函數(shù)還拿到了要插入的數(shù)據(jù)。是不是第三次插入成功了呢?不是的,其實(shí)正像第二次插入的一樣,肯定是主鍵重復(fù)了,但是由于我們并沒(méi)有要求返回最后的錯(cuò)誤狀態(tài),所以mongodb drvier直接回調(diào)了我們傳入的回調(diào)函數(shù),并且設(shè)置error為null,bars為要插入的數(shù)據(jù)??偨Y(jié)一下,如果你要確保數(shù)據(jù)是否更新(insert/update/remove)成功必須要設(shè)置{safe:true}選項(xiàng)。
更新Update
collection.update({a:996}, {$push: {b:'b'}}, function(error, bars){});
collection.update({a:996}, {$set: {a:997}}, function(error, bars){});
注意,這里為了代碼簡(jiǎn)單,我們沒(méi)有設(shè)置{safe:true}。你可以看到update的第一個(gè)參數(shù)是條件,即對(duì)a=996的文檔進(jìn)行更新。第二個(gè)參數(shù)則
是表示要如何更新文檔,譬如第一個(gè)update是增加一個(gè)屬性b,且設(shè)置其值為字符串'b';第二個(gè)update是修改a的值為997??梢钥闯?,第二個(gè)
參數(shù)是一個(gè)對(duì)象,其屬性名是一個(gè)操作符,以$開(kāi)頭,值為一個(gè)對(duì)象。這些操作符除了這里的$push和$set,還有其它的$inc, $unset,
$pushAll等等,具體可以參考這里。
刪除Delete
collection.remove({a:997}, {safe:true}, function(error, count){
console.log(error);
console.log(count);
collection.remove();
});
這里第一個(gè)remove是刪除a=997的所有文檔?;卣{(diào)函數(shù)的第二個(gè)參數(shù)是表示相應(yīng)刪除的文檔數(shù)量。第二個(gè)remove則是刪除該collection中的所有文檔。