mongoose:nodejs上簡(jiǎn)潔的mongodb對(duì)象模型坡贺。為什么要做mongoose旺矾,當(dāng)我們使用mongodb的時(shí)候片任,需要面對(duì)確認(rèn)器贩、投遞和商務(wù)邏輯等阻力颅夺,mongoose為此做了非常大的簡(jiǎn)化,非常簡(jiǎn)潔和優(yōu)美蛹稍。如下所示:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var Cat = mongoose.model('Cat', { name: String });
var kitty = new Cat({ name: 'Zildjian' });
kitty.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('meow');
}
});
使用mongoose
首先確認(rèn)已經(jīng)安裝了MongoDB和Node.js吧黄,下一步通過npm安裝Mongoose:
$ npm install mongoose
接下來我們要做的就是MongoDB數(shù)據(jù)庫的連接和連接信息的監(jiān)聽:
// getting-started.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
// we're connected!
});
一旦連接被打開,回調(diào)將會(huì)被調(diào)用唆姐。我們的代碼需要關(guān)注的就是在回調(diào)中進(jìn)行處理拗慨。對(duì)于Mongoose,所有的數(shù)據(jù)來源于 Schema奉芦。我們需要定義自己的Schema赵抢。
var kittySchema = mongoose.Schema({
name: String
});
var Kitten = mongoose.model('Kitten', kittySchema);
對(duì)于已經(jīng)定義的數(shù)據(jù)模型操作是非常簡(jiǎn)單的:
var silence = new Kitten({ name: 'Silence' });
console.log(silence.name); // 'Silence'
也可以為Schema模型定義函數(shù):
kittySchema.methods.speak = function () {
var greeting = this.name
? "Meow name is " + this.name
: "I don't have a name";
console.log(greeting);
}
var Kitten = mongoose.model('Kitten', kittySchema);
var fluffy = new Kitten({ name: 'fluffy' });
fluffy.speak(); // "Meow name is fluffy"
如果我們期望文檔存儲(chǔ)至數(shù)據(jù)庫:
fluffy.save(function (err, fluffy) {
if (err) return console.error(err);
fluffy.speak();
});
查詢文檔:
Kitten.find(function (err, kittens) {
if (err) return console.error(err);
console.log(kittens);
})
// 或者使用正則匹配,搜索所有文檔中名稱屬性中包含fluff字段的声功,在callback返回?cái)?shù)組結(jié)果
Kitten.find({ name: /^fluff/ }, callback);
mongoose的操作
Schema
一種以文件形式存儲(chǔ)的數(shù)據(jù)庫模型骨架烦却,無法直接通往數(shù)據(jù)庫端,也就是說它不具備對(duì)數(shù)據(jù)庫的操作能力.可以說是數(shù)據(jù)屬性模型(傳統(tǒng)意義的表結(jié)構(gòu))先巴,又或著是“集合”的模型骨架.
/* 定義一個(gè) Schema */
var mongoose = require("mongoose");
var TestSchema = new mongoose.Schema({
name : { type:String },//屬性name,類型為String
age : { type:Number, default:0 },//屬性age,類型為Number,默認(rèn)為0
time : { type:Date, default:Date.now },
email: { type:String,default:''}
});
上面這個(gè) TestSchema包含4個(gè)屬性 [name, age, time, email]
Model
由Schema構(gòu)造生成的模型其爵,除了Schema定義的數(shù)據(jù)庫骨架以外冒冬,還具有數(shù)據(jù)庫操作的行為,類似于管理數(shù)據(jù)庫屬性摩渺、行為的類:
var db = mongoose.connect("mongodb://127.0.0.1:27017/test");
// 創(chuàng)建Model
var TestModel = db.model("test1", TestSchema);
test1 數(shù)據(jù)庫中的集合名稱, 不存在會(huì)創(chuàng)建.
Entity
由Model創(chuàng)建的實(shí)體简烤,使用save方法保存數(shù)據(jù),Model和Entity都有能影響數(shù)據(jù)庫的操作摇幻,但Model比Entity更具操作性
var TestEntity = new TestModel({
name : "Lenka",
age : 36,
email: "lenka@qq.com"
});
console.log(TestEntity.name); // Lenka
console.log(TestEntity.age); // 36
ObjectId
存儲(chǔ)在mongodb集合中的每個(gè)文檔(document)都有一個(gè)默認(rèn)的主鍵_id横侦,這個(gè)主鍵名稱是固定的,它可以是mongodb支持的任何數(shù)據(jù)類型绰姻,默認(rèn)是ObjectId丈咐。
ObjectId是一個(gè)12字節(jié)的 BSON 類型字符串。按照字節(jié)順序龙宏,依次代表:
4字節(jié):UNIX時(shí)間戳
3字節(jié):表示運(yùn)行MongoDB的機(jī)器
2字節(jié):表示生成此_id的進(jìn)程
3字節(jié):由一個(gè)隨機(jī)數(shù)開始的計(jì)數(shù)器生成的值
Schema - 表結(jié)構(gòu)
1.構(gòu)造函數(shù)
new mongoose.Schema( { name:{type:String}, age:{type:Number, default:10} } )
2.添加屬性
Schema.add( { name: ‘String’, email: ‘String’, age: ‘Number’ } )
3.有時(shí)候Schema不僅要為后面的Model和Entity提供公共的屬性棵逊,還要提供公共的方法
Schema.method( ‘say’, function(){console.log(‘hello’);} )
//這樣Model和Entity的實(shí)例就能使用這個(gè)方法了
4.添加靜態(tài)方法
Schema.static( ‘say’, function(){console.log(‘hello’);} )
//靜態(tài)方法,只限于在Model層就能使用
5.追加方法
Schema.methods.say = function(){console.log(‘hello’);};
//靜態(tài)方法银酗,只限于在Model層就能使用
model - 文檔操作
1.構(gòu)造函數(shù), 參數(shù)1:集合名稱, 參數(shù)2:Schema實(shí)例
db.model(“test1”, TestSchema );
2.查詢, 參數(shù)1忽略,或?yàn)榭諏?duì)象則返回所有集合文檔
model.find({}, callback);
model.find({},field,callback);
過濾查詢,參數(shù)2: {‘name’:1, ‘a(chǎn)ge’:0} 查詢文檔的返回結(jié)果包含name , 不包含age.(_id默認(rèn)是1)
model.find({},null,{limit:20});
過濾查詢,參數(shù)3: 游標(biāo)操作 limit限制返回結(jié)果數(shù)量為20個(gè),如不足20個(gè)則返回所有.
model.findOne({}, callback);
查詢找到的第一個(gè)文檔
model.findById(‘obj._id’, callback);
查詢找到的第一個(gè)文檔,同上. 但是只接受 __id 的值查詢
3.創(chuàng)建, 在集合中創(chuàng)建一個(gè)文檔
Model.create(文檔數(shù)據(jù), callback))
4.更新,參數(shù)1:查詢條件, 參數(shù)2:更新對(duì)象,可以使用MondoDB的更新修改器
Model.update(conditions, update, function(error)
5.刪除, 參數(shù)1:查詢條件
Model.remove(conditions,callback);
Entity - 文檔操作
1.構(gòu)造函數(shù), 其實(shí)就是model的實(shí)例
new TestModel( { name:‘xueyou’, age:21 } );
2.創(chuàng)建, 在集合中創(chuàng)建一個(gè)文檔.
Entity.save(callback);
修改器和更新器
更新修改器:
‘$inc’ 增減修改器,只對(duì)數(shù)字有效.下面的實(shí)例: 找到 age=22的文檔,修改文檔的age值自增1
Model.update({‘a(chǎn)ge’:22}, {’$inc’:{‘a(chǎn)ge’:1} } );
執(zhí)行后: age=23
‘$set’ 指定一個(gè)鍵的值,這個(gè)鍵不存在就創(chuàng)建它.可以是任何MondoDB支持的類型.
Model.update({‘a(chǎn)ge’:22}, {’$set’:{‘a(chǎn)ge’:‘haha’} } );
執(zhí)行后: age=‘haha’
‘$unset’ 同上取反,刪除一個(gè)鍵
Model.update({‘a(chǎn)ge’:22}, {’$unset’:{‘a(chǎn)ge’:‘haha’} } );
執(zhí)行后: age鍵不存在
數(shù)組修改器:
‘$push’ 給一個(gè)鍵push一個(gè)數(shù)組成員,鍵不存在會(huì)創(chuàng)建
Model.update({‘a(chǎn)ge’:22}, {’$push’:{‘a(chǎn)rray’:10} } );
執(zhí)行后: 增加一個(gè) array 鍵,類型為數(shù)組, 有一個(gè)成員 10
‘$addToSet’ 向數(shù)組中添加一個(gè)元素,如果存在就不添加
Model.update({‘a(chǎn)ge’:22}, {’$addToSet’:{‘a(chǎn)rray’:10} } );
執(zhí)行后: array中有10所以不會(huì)添加
‘$each’ 遍歷數(shù)組, 和 $push 修改器配合可以插入多個(gè)值
Model.update({‘a(chǎn)ge’:22}, {’$push’:{‘a(chǎn)rray’:{’$each’: [1,2,3,4,5]}} } );
執(zhí)行后: array : [10,1,2,3,4,5]
‘$pop’ 向數(shù)組中尾部刪除一個(gè)元素
Model.update({‘a(chǎn)ge’:22}, {’$pop’:{‘a(chǎn)rray’:1} } );
執(zhí)行后: array : [10,1,2,3,4] tips: 將1改成-1可以刪除數(shù)組首部元素
‘$pull’ 向數(shù)組中刪除指定元素
Model.update({‘a(chǎn)ge’:22}, {’$pull’:{‘a(chǎn)rray’:10} } );
執(zhí)行后: array : [1,2,3,4] 匹配到array中的10后將其刪除
條件查詢:
“$lt” 小于
“$lte” 小于等于
“$gt” 大于
“$gte” 大于等于
“$ne” 不等于
Model.find({“age”:{ “$get”:18 , “$lte”:30 } } );
查詢 age 大于等于18并小于等于30的文檔
或查詢 OR:
‘$in’ 一個(gè)鍵對(duì)應(yīng)多個(gè)值
‘$nin’ 同上取反, 一個(gè)鍵不對(duì)應(yīng)指定值
“$or” 多個(gè)條件匹配, 可以嵌套 $in 使用
“$not” 同上取反, 查詢與特定模式不匹配的文檔
Model.find({“age”:{ “$in”:[20,21,22.‘haha’]} } );
查詢 age等于20或21或21或’haha’的文檔
Model.find({"$or" : [ {‘a(chǎn)ge’:18} , {‘name’:‘xueyou’} ] });
查詢 age等于18 或 name等于’xueyou’ 的文檔
類型查詢:
null 能匹配自身和不存在的值, 想要匹配鍵的值 為null, 就要通過 “$exists” 條件判定鍵值已經(jīng)存在
"$exists" (表示是否存在的意思)
Model.find(“age” : { “$in” : [null] , “exists” : true } );
查詢 age值為null的文檔
Model.find({name: {$exists: true}},function(error,docs){
//查詢所有存在name屬性的文檔
});
Model.find({telephone: {$exists: false}},function(error,docs){
//查詢所有不存在telephone屬性的文檔
});
正則表達(dá)式:
MongoDb 使用 Prel兼容的正則表達(dá)式庫來匹配正則表達(dá)式
find( {“name” : /joe/i } )
查詢name為 joe 的文檔, 并忽略大小寫
find( {“name” : /joe?/i } )
查詢匹配各種大小寫組合
查詢數(shù)組:
Model.find({“array”:10} );
查詢 array(數(shù)組類型)鍵中有10的文檔, array : [1,2,3,4,5,10] 會(huì)匹配到
Model.find({“array[5]”:10} );
查詢 array(數(shù)組類型)鍵中下標(biāo)5對(duì)應(yīng)的值是10, array : [1,2,3,4,5,10] 會(huì)匹配到
‘$all’ 匹配數(shù)組中多個(gè)元素
Model.find({“array”:[5,10]} );
查詢 匹配array數(shù)組中 既有5又有10的文檔
‘$size’ 匹配數(shù)組長(zhǎng)度
Model.find({“array”:{"$size" : 3} } );
查詢 匹配array數(shù)組長(zhǎng)度為3 的文檔
‘$slice’ 查詢子集合返回
Model.find({“array”:{"$skice" : 10} } );
查詢 匹配array數(shù)組的前10個(gè)元素
Model.find({“array”:{"$skice" : [5,10] } } );
查詢 匹配array數(shù)組的第5個(gè)到第10個(gè)元素
where
用它可以執(zhí)行任意javacript語句作為查詢的一部分,如果回調(diào)函數(shù)返回 true 文檔就作為結(jié)果的一部分返回
find( {"$where" : function(){
for( var x in this ){
//這個(gè)函數(shù)中的 this 就是文檔
}
if(this.x !== null && this.y !== null){
return this.x + this.y === 10 ? true : false;
}else{
return true;
}
} } )
簡(jiǎn)化版本
find( {"$where" : "this.x + this.y === 10" } )
find( {"$where" : " function(){ return this.x + this.y ===10; } " } )
游標(biāo):
limit(3) 限制返回結(jié)果的數(shù)量,
skip(3) 跳過前3個(gè)文檔,返回其余的
sort( {“username”:1 , “age”:-1 } ) 排序 鍵對(duì)應(yīng)文檔的鍵名, 值代表排序方向, 1 升序, -1降序
補(bǔ)充:
使用rename
db.students.update( { _id: 1 }, { $rename: { 'nickname': 'alias', 'cell': 'mobile' } } )
批量appkey改成appid
db.app.update({},{$rename:{"appkey":"appid"}},{multi:true})
參考:
http://mongoosejs.com/docs/guide.html
https://cnodejs.org/topic/548e54d157fd3ae46b233502