亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB開發 > 正文

mongoose 筆記

2024-04-27 15:06:51
字體:
來源:轉載
供稿:網友

快速啟動

首先需要安裝MongoDB和Node.js。 然后使用npm下載mongoose: npm install mongoose 接著我們直接在項目中引入mongoose,并且連接數據庫就會在本地運行 MongoDB了:

// index.jsvar mongoose = require('mongoose');mongoose.connect('mongodb://localhost/demo');

用node命令執行index.js,demo數據庫就會在本地運行了。我們需要在連接數據庫成功或者失敗的時候有些提示,可以這樣添加代碼:

var db = mongoose.connection;db.on('error', console.error.bind(console, 'connection error:'));db.once('open', function (callback) { // 后續代碼默認都寫在這里!});

連接成功的時候就會執行一次回調函數,現在假設下面所有代碼都是在成功的回調函數中的。

Mongoose中,所有東西都是衍生自Schema。 Schema(模式)就像是Model(模型)的抽象類一樣的存在,創建一個Schema

var mySchema =new mongoose.Schema({ name: String});

我們創建了一個叫mySchemaSchema,并且定義了一個屬性name,限定類型是String。接著可以用mySchema創建一個Model

var MyModel = mongoose.model('MyModel', mySchema);

這樣就按照mySchema創建了一個MyModel模型,這個MyModel其實充當了兩個作用:

充當MongoDB中的collection(集合)是用來構造document(文檔)的類

所以要構造一條document只要:

var instance = new MyModel({ name: ' Instance' })console.log( instance.name) // 'instance'

instance就是一條也可以稱作Document了。

如此看來Schema、ModelDocument的關系就像是抽象類、實現類和實例三者的關系一樣。所以嘛,自然可以在Schema定義后添加方法:

var mySchema =new mongoose.Schema({ name: String});mySchema.methods.getName=function(){ console.log(this.name + "來自getName方法");}...instance.getName();//'instance來自getName方法'

instance實例現在還沒有被保存在MongoDB中,所有的實例都要調用save方法后才會保存進數庫:

instance.save((err,instance)=>{ if (err) return console.error(err); instance.getName();})

而后,需要查詢數據時就需要使用Model,因為Model的作用時充當MongoDB中的collection(集合),所以這樣查詢數據:

MyModel.find(function (err, instances) { if (err) return console.error(err); console.log(instances);});

當然了,也可以加條件查詢:

MyModel.find({name:"instance"},callback);

這樣就是一個完整的使用mongoose插入和查詢數據的操作了。完整代碼如下:

var mongoose = require('mongoose');var db = mongoose.connection;db.on('error', console.error.bind(console, 'connection error:'));db.once('open', function(callback) { var mySchema =new mongoose.Schema({ name: String }); mySchema.methods.getName = function() { console.log(this.name + "來自getName方法"); } var MyModel = mongoose.model('MyModel', mySchema); var instance = new MyModel({ name: ' Instance' }) console.log(instance.name) // 'instance' instance.getName(); //'instance' instance.save((err, instance) => { if (err) { return console.error(err) }; instance.getName(); })});mongoose.connect('mongodb://localhost/test');

Schemas

定義schema

Mongoose所有的一切始于Schema。每一個Schema都映射到MongoDB中的collection(集合)和定義了document(文檔)的結構。

var mongoose = require('mongoose');var Schema = mongoose.Schema;var blogSchema = new Schema({ title: String, author: String, body: String, comments: [{ body: String, date: Date }], date: { type: Date, default: Date.now }, hidden: Boolean, meta: { votes: Number, favs: Number }});

如果想要在創建Schema以后添加額外的key,可以使用Schema的add方法。

現在只需要知道SchemaTypes有:

StringNumberDateBufferBooleanMixedObjectIdArray

創建了Schema后肯定就是創建Model了,然而,在這之間我們還可以定義instance方法、定義靜態Model方法、定義索引和使用生命周期掛鉤(中間件)

instance方法

instance方法使用schemamethods添加,這樣做可以讓創建的documents在save之前執行一些自定義的操作:

// define a schemavar animalSchema = new Schema({ name: String, type: String });// assign a function to the "methods" object of our animalSchemaanimalSchema.methods.findSimilarTypes = function (cb) { return this.model('Animal').find({ type: this.type }, cb);}//define a modelvar Animal = mongoose.model('Animal', animalSchema);//instancevar dog = new Animal({ type: 'dog' });dog.findSimilarTypes(function (err, dogs) { console.log(dogs); // woof});

這樣做要注意的是不要重寫mongoose原來的document方法,不然會有未知錯誤。

靜態Model方法

methods上添加的是給document用的,而在statics上添加的方法就是給Model用的:

// assign a function to the "statics" object of our animalSchemaanimalSchema.statics.findByName = function (name, cb) { this.find({ name: new RegExp(name, 'i') }, cb);}var Animal = mongoose.model('Animal', animalSchema);Animal.findByName('fido', function (err, animals) { console.log(animals);});

索引

MongoDB支持使用索引。在mongoose中,分別可以在內部和外部定義,不過復合索引就只能在外部定義了:

var animalSchema = new Schema({ name: String, type: String, tags: { type: [String], index: true } // 內部});animalSchema.index({ name: 1, type: -1 }); // 外部,復合索引

當應用啟動,Mongoose就會自動調用ensureIndex為每個schema創建索引。索引創建會有顯著的性能影響,所以建議在生產環境中禁用:

animalSchema.set('autoIndex', false);// ornew Schema({..}, { autoIndex: false });

虛擬屬性

虛擬屬性是一種不會存儲進數據庫但是存在在doucment中的屬性。充當gettersetter的功能。 基本代碼:

var personSchema = new Schema({ name: { first: String, last: String }});// compile our modelvar Person = mongoose.model('Person', personSchema);// create a documentvar bad = new Person({ name: { first: 'Walter', last: 'White' }});

當調用toObject和toJSON方法時默認都是不會有虛擬屬性的。 現在想訪問bad.name.full就給出全名,就要使用虛擬屬性的getter功能:

personSchema.virtual('name.full').get(function () { return this.name.first + ' ' + this.name.last;});。。。console.log('%s is insane', bad.name.full); // Walter White is insane

同樣的有setter功能:

personSchema.virtual('name.full').set(function (name) { var split = name.split(' '); this.name.first = split[0]; this.name.last = split[1];});...bad.name.full = 'Breaking Bad';console.log(bad.name.first); // Breakingconsole.log(bad.name.last); // Bad

options

Schemas在構建實例或者通過set方法可以進行有options的配置:

new Schema({..}, options);// 或者var schema = new Schema({..});schema.set(option, value);

options:

autoIndex:自動索引cappedcollectionid_idreadsafeshardKeystricttoJSONtoObject

versionKey

autoIndex

在應用啟動時,Mongoose會調用ensureIndex為Schema構建索引。自Mongoose v3起,索引默認都會在后臺創建。如果想關閉自動創建或者以后手動創建索引,可以進行如下設置:

var schema = new Schema({..}, { autoIndex: false });var Clock = mongoose.model('Clock', schema);Clock.ensureIndexes(callback);

bufferCommands

capped

Mongoose支持MongoDB的固定大小集合,直接設置capped表示最大空間,單位時bytes,當然也可以使用對象設置max(最大document數)和autoIndexId

new Schema({..}, { capped: 1024 });//或者new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });

collection

Mongoose中collection的名字默認時注冊Model時的名字,如果想要自定義,可以這樣設置:

var dataSchema = new Schema({..}, { collection: 'data' });

id

document都會設置一個虛擬屬性id并配置getter來獲取_id,如果不想要id虛擬屬性可以設為false

// default behaviorvar schema = new Schema({ name: String });var Page = mongoose.model('Page', schema);var p = new Page({ name: 'mongodb.org' });console.log(p.id); // '50341373e894ad16347efe01'// disabled idvar schema = new Schema({ name: String }, { id: false });var Page = mongoose.model('Page', schema);var p = new Page({ name: 'mongodb.org' });console.log(p.id); // undefined

_id

Mongoose默認會在生成document的時候生成_id字段,如果想禁止這個行為可以設為false,但是插入數據庫的時候仍然會有_id字段:

// default behaviorvar schema = new Schema({ name: String });var Page = mongoose.model('Page', schema);var p = new Page({ name: 'mongodb.org' });console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }// disabled _idvar schema = new Schema({ name: String }, { _id: false });// 不要使用schema.set("_id",false),var Page = mongoose.model('Page', schema);var p = new Page({ name: 'mongodb.org' });console.log(p); // { name: 'mongodb.org' }// MongoDB 會在數據被插入的時候給_idp.save(function (err) { if (err) return handleError(err); Page.findById(p, function (err, doc) { if (err) return handleError(err); console.log(doc); // { name: 'mongodb.org', _id: '50341373e894ad16347efe12' } })})

read

設置讀寫分離屬性:

var schema = new Schema({..}, { read: 'safe

shardKey

strict

mongoose默認會開啟嚴格模式,所有不是在Schema定義的屬性都不會被保存進數據庫,將strict設為false就會:

var thingSchema = new Schema({..})var Thing = mongoose.model('Thing', thingSchema);var thing = new Thing({ iAmNotInTheSchema: true });thing.save(); // iAmNotInTheSchema不會保存進數據庫// 設為 false..var thingSchema = new Schema({..}, { strict: false });var thing = new Thing({ iAmNotInTheSchema: true });thing.save(); // iAmNotInTheSchema會保存進數據庫

還支持在instance的時候設置:

var thing = new Thing(doc, false); // 關閉嚴格模式

除了boolean,也可以設置為throw,但是這樣會拋出錯誤,而不時忽略值。 提示:不要手賤設為false 提示:在mongoose v2 默認只時false 提示:直接在document上set的只都不會被保存

var thingSchema = new Schema({..})var Thing = mongoose.model('Thing', thingSchema);var thing = new Thing({},false);thing.iAmNotInTheSchema = true;thing.save(); // iAmNotInTheSchema is never saved to the db

toJSON和toObject

兩個方法類似,都是輸出格式化對象:

var schema = new Schema({ name: String });schema.path('name').get(function (v) { return v + ' is my name';});//默認是不使用getter和不輸出virtualschema.set('toJSON', { getters: true, virtuals: false });var M = mongoose.model('Person', schema);var m = new M({ name: 'Max Headroom' });console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }// stringify內部會調用toJSONconsole.log(JSON.stringify(m));//console內部時調用toObjectconsole.log(m);

versionKey

設置document的version鍵,默認鍵是_v,設為false的話就沒有這個version:

var schema = new Schema({ name: 'string' });var Thing = mongoose.model('Thing', schema);var thing = new Thing({ name: 'mongoose v3' });thing.save(); // { __v: 0, name: 'mongoose v3' }// 換 versionKeynew Schema({..}, { versionKey: '_somethingElse' })var Thing = mongoose.model('Thing', schema);var thing = new Thing({ name: 'mongoose v3' });thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }//設為falsenew Schema({..}, { versionKey: false });var Thing = mongoose.model('Thing', schema);var thing = new Thing({ name: 'no versioning please' });thing.save(); // { name: 'no versioning please' }

Models

Models在Schema和document中作承上啟下,作用有兩個: - 充當MongoDB中的collection(集合) - 是用來構造document(文檔)的類 所以document的創建和檢索都是來自于Models的方法。

第一個model

var schema = new mongoose.Schema({ name: 'string', size: 'string' });var Tank = mongoose.model('Tank', schema);

構造documents

var Tank = mongoose.model('Tank', yourSchema);var small = new Tank({ size: 'small' });small.save(function (err) { if (err) return handleError(err); // saved!})// orTank.create({ size: 'small' }, function (err, small) { if (err) return handleError(err); // saved!})

查詢

查詢操作有諸如find, findById, findOne, 和 where等方法,直接查API:

Tank.find({ size: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

移除

Models有個remove方法可以用于移除指定條件的documents:

Tank.remove({ size: 'large' }, function (err) { if (err) return handleError(err); // removed!});

更新

Models有個update方法可以用于更新指定條件的documents:

let query = { age: { $gt: 18 } };//查詢條件let updated = { oldEnough: true };//更新結果 也可以是{ $set: { name: 'jason borne' }}MyModel.update(query,updated ,options, fn);

Documents

如果說Models(也就為collection)相當于SQL數據庫中的表的話,那么Document就相當于了。

更新

數據的更新操作也可以直接使用在document:

Tank.findById(id, function (err, tank) { if (err) return handleError(err); tank.size = 'large'; tank.save(function (err) { if (err) return handleError(err); res.send(tank); });});

子文檔

在構建Schema可以使用另外一個Schema作為數據類型:

var childSchema = new Schema({ name: 'string' });var parentSchema = new Schema({ children: [childSchema]})

保存文檔的時候,子文檔在數據庫并不會獨自使用集合保存,數據庫中保存的只有父文檔的集合。不過每個子文檔都會有一個_id

var Parent = mongoose.model('Parent', parentSchema);var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })parent.children[0].name = 'Matthew';parent.save(callback);//保存后數據庫中只有Parent集合var doc = parent.children.id(id);//使用`id`方法可以檢索子文檔

但是子文檔如果的生命周期有掛鉤的話也是會執行的:

childSchema.pre('save', function (next) { if ('invalid' == this.name) return next(new Error('#sadpanda')); next();});var parent = new Parent({ children: [{ name: 'invalid' }] });parent.save(function (err) { console.log(err.message) // #error : sadpanda})

添加子文檔

MongooseArray方法有想 push, unshift, addToSet等等可以添加子文檔:

var Parent = mongoose.model('Parent');var parent = new Parent;// create a commentparent.children.push({ name: 'Liesl' });var subdoc = parent.children[0];console.log(subdoc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }subdoc.isNew; // trueparent.save(function (err) { if (err) return handleError(err) console.log('Success!');});//或者var newdoc = parent.children.create({ name: 'Aaron' });

移除子文檔

移除子文檔可以使用remove方法:

var doc = parent.children.id(id).remove();parent.save(function (err) { if (err) return handleError(err); console.log('the sub-doc was removed')});

字面聲明語法

在v3版本允許直接聲明對象聲明子文檔:

var parentSchema = new Schema({ children: [{ name: 'string' }]})

查詢

所有model的查詢操作都會有兩種形式: - 當有回調方法作為參數時:會將查詢操作的結果傳遞給回調方法; - 當沒有回調方法作為參數時:會將查詢結果封裝成一個QueryBuilder接口返回。 先看看有回調方法是怎樣的:

var Person = mongoose.model('Person', yourSchema);// find each person with a last name matching '
Ghost', selecting the `name` and `occupation` fieldsPerson.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { if (err) return handleError(err); console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.})

在Mongoose中的查詢回調方法的形式都類似于:callback(error, result)。result不一定都是document的list,要看具體是什么操作。

再來看看沒有回調函數的寫法:

// find each person with a last name matching 'Ghost'var query = Person.findOne({ 'name.last': 'Ghost' });// selecting the `name` and `occupation` fieldsquery.select('name occupation');// execute the query at a later timequery.exec(function (err, person) { if (err) return handleError(err); console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.})//也可以使用鏈式操作Person.findOne({ 'name.last': 'Ghost' }).select('name occupation').exec(callback);

上面三種寫法是做同一件事情,不加回調參數時,要使用exec才會執行所有操作。

驗證

Mongoose有幾個內置的驗證器: - 所有的 SchemaTypes 都可以聲明required; - Nembers 有 minmax; - String有enummatch驗證。 所有的這些都可以在 Schema創建時進行聲明。

自定義驗證

用戶還可以使用validate方法自定義驗證規則:

var toySchema = new Schema({ color: String, name: String});var Toy = mongoose.model('Toy', toySchema);//自定義驗證規則Toy.schema.path('color').validate(function (value) { return /blue|green|white|red|orange|periwinkle/i.test(value);}, 'Invalid color');var toy = new Toy({ color: 'grease'});toy.save(function (err) { // err is our ValidationError object // err.errors.color is a ValidatorError object console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color with value `grease`' console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color with value `grease`' console.log(err.errors.color.type) // prints "Invalid color" console.log(err.errors.color.path) // prints "color" console.log(err.errors.color.value) // prints "grease" console.log(err.name) // prints "ValidationError" console.log(err.message) // prints "Validation failed"});

驗證錯誤觸發后,document會有一個errors屬性:

toy.errors.color.message === err.errors.color.message

中間件

Mongoose允許在文檔的init,validate,saveremove的前后觸發一些方法

Pre

前置有兩種形式,串行和并行。

串行

var schema = new Schema(..);schema.pre('save', function (next) { // 中間件一個接一個 next();});

并行

var schema = new Schema(..);schema.pre('save', true, function (next, done) { // 異步執行中間件 next(); doAsync(done);});

錯誤傳遞

pre可以將傳遞錯誤:

schema.pre('save', function (next) { var err = new Error('something went wrong'); next(err);});// later...myDoc.save(function (err) { console.log(err.message) // something went wrong});

Post

Post中間件是在指定操作完成后,回調函數還沒有執行前執行的方法:

parentSchema.pre("save", function(next, done) { console.log("pre save"); next(); console.log("after pre save"); })parentSchema.post("save", function() { console.log("post save"); })...parent.save(function(err) { if (err) { console.log(err); return; } console.log("save"); });/*consolepre saveafter pre savepost savesave*/

Population

MongoDB是文檔型數據庫,所以沒有關系型數據庫joins(數據庫的兩張表通過”外鍵”,建立連接關系。) 特性。建立數據關聯時會非常麻煩,Mongoose就封裝了Population實現document中填充其他collection的document。

建立關聯

能建立關聯的字段只有ObjectId, Number, String, and Buffer四種類型可以。建立關聯只需要在聲明Schema的時候使用ref屬性就可以關聯:

var mongoose = require('mongoose') , Schema = mongoose.Schemavar personSchema = Schema({ _id : Number, name : String, age : Number, stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]});var storySchema = Schema({ _creator : { type: Number, ref: 'Person' }, title : String, fans : [{ type: Number, ref: 'Person' }]});var Story = mongoose.model('Story', storySchema);var Person = mongoose.model('Person', personSchema);

storySchema中_creator和fans字段都關聯了Person,并且都將type設為Number。這是因為,Person和Story建立了關聯后,Story中的document的_creator或fans字段是通過Person的_id屬性關聯對應數據的,所以Story的_creator和fans要與Person的_id類型保持一致。

保存refs

要先保存被關聯的document(Person),并且將_id注冊進去:

var aaron = new Person({ _id: 0, name: 'Aaron', age: 100 });aaron.save(function (err) { if (err) return handleError(err); var story1 = new Story({ title: "Once upon a timex.", _creator: aaron._id // 這里可以直接用aaron }); story1.save(function (err) { if (err) return handleError(err); // thats it! });})

當然了注冊的時候直接寫個0也可以,這個ref只是在檢索Person的_id字段的依據的時候。

關聯查詢

現在只需要在關聯查詢的時候使用populate聲明關聯字段就會進行關聯查詢的:

Story.findOne({ title: 'Once upon a timex.' }).populate('_creator').exec(function (err, story) { if (err) return handleError(err); console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"})

_creator字段就會被關聯document給替換了。數組也是同樣的道理,每個元素都會被相應的document給替換。

字段篩選

可以對被關聯的document進行篩選:

Story.findOne({ title: /timex/i }).populate('_creator', 'name') // 只返回name字段.exec(function (err, story) { if (err) return handleError(err); console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron" console.log('The creators age is %s', story._creator.age); // prints "The creators age is null'})

多關聯

在3.6版本后可以使用空格分割populate:

Story.find(...).populate('fans author') //使用空格分開.exec()

但是在3.6之前就只能鏈式操作:

Story.find(...).populate('fans').populate('author').exec()

查詢參數

查詢的時候可以使用其他參數:

Story.find(...).populate({ path: 'fans', match: { age: { $gte: 21 }}, select: 'name -_id', options: { limit: 5 }}).exec()

Plugins

Schemas允許添加插件,這樣就會想繼承一樣,每個Schemas都會有插件中定義的功能:

// lastMod.jsmodule.exports = exports = function lastModifiedPlugin (schema, options) { schema.add({ lastMod: Date }) schema.pre('save', function (next) { this.lastMod = new Date next() }) if (options && options.index) { schema.path('lastMod').index(options.index) }}// game-schema.jsvar lastMod = require('./lastMod');var Game = new Schema({ ... });Game.plugin(lastMod, { index: true });// player-schema.jsvar lastMod = require('./lastMod');var Player = new Schema({ ... });Player.plugin(lastMod);

Game和Player就都會有lastMod中定義的功能。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久精品一区二区三区| 久久久久久亚洲| 欧美色另类天堂2015| 精品国产一区二区三区在线观看| 亚洲国产成人在线播放| 色妞在线综合亚洲欧美| 一区二区三区视频在线| 91精品久久久久久久久不口人| 岛国av午夜精品| 欧美一级高清免费播放| 亚洲精品国产欧美| 成人午夜激情网| 国内成人精品一区| 免费不卡欧美自拍视频| 清纯唯美日韩制服另类| 亚洲精品乱码久久久久久金桔影视| 国产91精品久久久久久| 伦伦影院午夜日韩欧美限制| 国产裸体写真av一区二区| 亚洲激情在线视频| 国产美女主播一区| 97精品视频在线播放| 久久综合免费视频| 国产mv免费观看入口亚洲| 最近的2019中文字幕免费一页| 国外成人性视频| 亚洲一区二区三区毛片| 欧美日韩裸体免费视频| 怡红院精品视频| 九九热视频这里只有精品| 日韩女优在线播放| 国产成人精品亚洲精品| 色多多国产成人永久免费网站| 国产精品久久久一区| 国产精品久久久999| 国产区精品视频| 国产精品尤物福利片在线观看| 超薄丝袜一区二区| 黄色精品在线看| 日韩欧美极品在线观看| 日韩精品中文在线观看| 久久久国产精品亚洲一区| 亚洲综合中文字幕在线| 国产精品入口免费视频一| 日韩高清有码在线| 欧美成人性色生活仑片| 51精品国产黑色丝袜高跟鞋| 中文.日本.精品| 黑人狂躁日本妞一区二区三区| 91精品久久久久久久久久久久久| 国产精品黄页免费高清在线观看| 日韩欧美在线字幕| 亚洲精品网站在线播放gif| 91最新国产视频| 亚洲性线免费观看视频成熟| 久久国产加勒比精品无码| 成人黄色在线观看| 国产精品久久婷婷六月丁香| 粉嫩av一区二区三区免费野| 亚洲天堂久久av| 欧美国产日韩一区二区在线观看| 2020欧美日韩在线视频| 欧美国产在线视频| 色综合久综合久久综合久鬼88| 午夜精品久久久久久99热软件| 久久人人爽人人爽爽久久| 欧美午夜www高清视频| 国产精品天天狠天天看| 欧美一级高清免费| 亚洲精品电影网站| 日韩精品视频免费在线观看| 岛国av一区二区三区| 91在线免费看网站| 国产欧洲精品视频| 日韩欧美一区视频| 一区二区三区高清国产| 国产精品九九九| 日本国产欧美一区二区三区| 欧美成人sm免费视频| 这里只有精品视频在线| 国内外成人免费激情在线视频网站| 亚洲国产欧美久久| 欧美日韩在线观看视频| 成人网址在线观看| 亚洲精品福利在线| 亚洲欧美国产精品va在线观看| 亚洲欧美一区二区三区情侣bbw| 亚洲欧美精品中文字幕在线| 日韩在线www| 少妇高潮久久77777| 亚洲乱码国产乱码精品精天堂| 久久久久女教师免费一区| 国内精品久久久久久久久| 欧美限制级电影在线观看| 一区二区欧美激情| 久久久久久久久久久久久久久久久久av| 亚洲男女自偷自拍图片另类| 精品久久久久久久久久国产| 17婷婷久久www| 亚洲人精品午夜在线观看| 欧美xxxx18国产| 国产精品福利在线| 成人激情春色网| 日韩在线视频一区| 国产日韩欧美在线视频观看| 亚洲mm色国产网站| 国产精品黄页免费高清在线观看| 国产不卡一区二区在线播放| 精品国产一区二区三区在线观看| 国产精品99久久久久久久久久久久| 欧美最猛黑人xxxx黑人猛叫黄| 欧美视频第一页| 欧美综合一区第一页| 亚洲国产精品va在线看黑人| 色综合久久精品亚洲国产| 97香蕉超级碰碰久久免费的优势| 国产大片精品免费永久看nba| 亚洲国产成人精品一区二区| 久久精品91久久香蕉加勒比| 久久精品国产清自在天天线| 日韩视频一区在线| 国模视频一区二区| 中文字幕国产亚洲2019| 日韩免费观看在线观看| 国产日韩中文字幕| 亚洲一品av免费观看| 精品无人区太爽高潮在线播放| 欧美日韩一区二区在线播放| 91精品视频在线免费观看| 国产精品久久不能| 久久久久久久久综合| 久久免费少妇高潮久久精品99| 国内精品久久久久久中文字幕| 欧美精品在线看| 日韩黄色av网站| 国产精品老女人视频| 91夜夜未满十八勿入爽爽影院| 中文字幕日韩精品有码视频| 欧美国产第一页| 亚洲一区亚洲二区亚洲三区| 久久久国产一区二区三区| 黄色成人av网| 国产主播在线一区| 精品久久久久久亚洲精品| 一本色道久久88综合亚洲精品ⅰ| 国产激情视频一区| 国产精品网站视频| 疯狂做受xxxx高潮欧美日本| 欧美性受xxxx白人性爽| 亚洲精品国产综合区久久久久久久| 国产精品高清免费在线观看| 在线观看免费高清视频97| 久久香蕉国产线看观看av| 国产精品一二区| 色婷婷av一区二区三区在线观看| 久久91亚洲精品中文字幕奶水| 亚洲日本aⅴ片在线观看香蕉| 精品日韩视频在线观看| 亚洲电影av在线| 欧美黑人极品猛少妇色xxxxx| 成人国产在线激情| 久久久精品999| 国产精品白嫩初高中害羞小美女| 精品亚洲va在线va天堂资源站|