连接mongoose

mongoose连接数据库有两种方式
第一种:

'use strict';

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/test');
const con = mongoose.connection;
con.on('error', console.error.bind(console, '连接数据库失败'));
con.once('open',()=>{
//成功连接
})

第二种:

var mongoose = require('mongoose');

db = mongoose.createConnection('localhost', 'test');
var schema = new mongoose.Schema({ name: String });
var collectionName = 'kittens';
var M = db.model('Kitten', schema, collectionName);
var silence = new M({ name: "Silence"});
silence.save(function(err){ });

mongoose.createConnection()和mongoose.connect()区别

首先,我们需要定义一个连接,如果你的app只用到一个数据库,你应该使用 mongoose.connect。如果你还需要连接其他数据库,使用mongoose.createConnection。
所有的 connect and createConnection 使用 mongodb:// URI, or the parameters host, database, port, options.等参数

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/my_database');

一旦连接,Connection对象会触发open事件,如果你使用 mongoose.connect, Connection对象就是默认的 mongoose.connection,而使用 mongoose.createConnection 返回值就是 Connection.

Mongoose会缓存所有命令直到连接上数据库,这意味着你不必等待它连接MongoDB再定义 models,执行 queries 等。

Mongoose基本概念

  • Schema: 表定义模板
  • Model: 类似关系数据库表,封装成具有一些集合操作的对象
  • instance: 类似记录,由Model创建的实体,也具有影响数据库的操作

基本用法

//定义一个schema
let Schema = mongoose.Schema({
category:String,
name:String
});
Schema.methods.eat = function(){
console.log("I've eatten one "+this.name);
}
//继承一个schema
let Model = mongoose.model("fruit",Schema);
//生成一个document
let apple = new Model({
category:'apple',
name:'apple'
});
//存放数据
apple.save((err,apple)=>{
if(err) return console.log(err);
apple.eat();
//查找数据
Model.find({name:'apple'},(err,data)=>{
console.log(data);
})
});

Schema

// from mongoose author
var mongoose = require('mongoose');
var Schema = mongoose.Schema;//引用出来,不需要每次调用 mongoose.Schema()这个丑陋的API. var blogSchema = new Schema({
title: String,
author: String,
//直接写法,会被转化成相应的SchemaType
body: String,
comments: [{ body: String, date: Date }],
//定义SchemaType写法
date: { type: Date, default: Date.now },
hidden: Boolean,
meta: {
votes: Number,
favs: Number
}
});

Schema 之所以能够定义documents, 是因为他可以限制你输入的字段及其类型. mongoose支持的基本类型有:

  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • ObjectId
  • Array

SchemaType

type属性指定SchemaType类型,不同的SchemaType类型还有其他不同的属性配置

var schema2 = new Schema({
test: {
type: String,
lowercase: true // Always convert `test` to lowercase
}
});

这是所有类型公有的:

  • required: 必选验证器。
  • default: 默认值。Any或function,如果该值是一个函数,则该函数的返回值将用作默认值。
  • select: boolean值, 指定是否被投影
  • `validate: 验证器
  • get: get方法,using Object.defineProperty().
  • set: set方法 using Object.defineProperty().
  • alias: 别名。

其他类型特有属性官方API查找。

设置索引

这里设置索引分两种,一种设在Schema filed, 另外一种设在 Schema.index 里.

//在field 设置
var animalSchema = new Schema({
name: String,
type: String,
tags: { type: [String], index: true }
});

//在Schema.index中设置.

animalSchema.index({ name: 1, type: -1 });

//1 表示正序, -1 表示逆序

实际上,两者效果是一样的. 看每个人的喜好了. 不过推荐直接在Schema level中设置, 这样分开能够增加可读性. 不过,
可以说,当应用启动的时候, ,Mongoose会自动为Schema中每个定义了索引的调用ensureIndex,确保生成索引.
并在所有的secureIndex调用成功或出现错误时,在 Model 上发出一个'index'事件。 开发环境用这个很好, 但是建议在生产环境不要使用这个.使用下面的方法禁用ensureIndex。
通过将 Schema 的autoIndex选项设置为false或通过将选项config.autoIndex设置为false将连接全局设置为禁用此行为 有可能严重拖慢查询或者创建速度,所以一般而言,我们需要将该option 关闭.

mongoose.connect('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } });  //真心推荐
// or
mongoose.createConnection('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } }); //不推荐
// or
animalSchema.set('autoIndex', false); //推荐
// or
new Schema({..}, { autoIndex: false }); //懒癌不推荐
// Will cause an error because mongodb has an _id index by default that
// is not sparse
animalSchema.index({ _id: 1 }, { sparse: true });
var Animal = mongoose.model('Animal', animalSchema); Animal.on('index', function(error) {
// "_id index cannot be sparse"
console.log(error.message);
});

定义Schema.methods

// 定义一个schema
var freshSchema = new Schema({ name: String, type: String }); // 添加一个fn.
animalSchema.methods.findSimilarTypes = function (cb) {
//这里的this指的是具体document上的this
//this.model 返回Model对象
return this.model ('Animal').find({ type: this.type }, cb);
}
// 实际上,我们可以通过schema绑定上,数据库操作的所有方法.
// 该method实际上是绑定在 实例的 doc上的

实例Model

这里同样很简单,只需要 mongoose.model() 即可.

//生成,model 类. 实际上就相当于我们的一个collection
var Animal = mongoose.model('Animal', animalSchema);
var dog = new Animal({ type: 'dog' });

但是, 这里有个问题. 我们在Schema.methods.fn 上定义的方法,只能在 new Model() 得到的实例中才能访问. 那如果我们想,直接在Model上调用 相关的查询或者删除呢?

绑定Model方法

同样很简单,使用 Statics 即可.

// 给model添加一个findByName方法
animalSchema.statics.findByName = function (name, cb) {
//这里的this 指的就是Model
return this.find({ name: new RegExp(name, 'i') }, cb);
} var Animal = mongoose.model('Animal', animalSchema);
Animal.findByName('fido', function (err, animals) {
console.log(animals);
});

虚拟属性

Mongoose 还有一个super featrue-- virtual property 该属性是直接设置在Schema上的. 但是,需要注意的是,VR 并不会真正的存放在db中. 他只是一个提取数据的方法.

//schema基本内容
var personSchema = new Schema({
name: {
first: String,
last: String
}
}); // 生成Model
var Person = mongoose.model('Person', personSchema); //现在我们有个需求,即,需要将first和last结合输出.
//一种方法是,使用methods来实现
//schema 添加方法
personSchema.methods.getName = function(){
return this.first+" "+this.last;
} // 生成一个doc
var bad = new Person({
name: { first: 'jimmy', last: 'Gay' }
}); //调用
bad.getName();

但是,像这样,仅仅这是为了获取一个属性, 实际上完全可以使用虚拟属性来实现.

//schema 添加虚拟属性
personSchema.virtual('fullName').get(function(){
return this.first+" "+this.last;
})
//调用
bad.fullName; //和上面的方法的结果是完全一致的

而且,经过测试, 使用fn实现的返回,比VR 要慢几十倍. 一下是测试结果:

console.time(1);
bad.getName();
console.timeEnd(1);
console.time(2);
bad.fullName;
console.timeEnd(2); //结果为:
1: 4.323ms; //method
2: 0.253ms // VR

最后再补充一下,Schema中初始化的相关参数.
Schema参数 在 new Schema([options]) 中,我们需要设置一些相关的参数.

  • safe: 用来设置安全模式. 实际上,就是定义入库时数据的写入限制. 比如写入时限等.
//使用安全模式. 表示在写入操作时,如果发生错误,也需要返回信息.
var safe = true;
new Schema({ .. }, { safe: safe }); // 自定义安全模式. w为写入的大小范围. wtimeout设置写入时限. 如果超出10s则返回error
var safe = { w: "majority", wtimeout: 10000 };
new Schema({ .. }, { safe: safe });
  • toObject: 用来表示在提取数据的时候, 把documents 内容转化为Object内容输出. 一般而言只需要设置getters为true即可.
var schema = new Schema({ name: String });
schema.path('name').get(function (v) {
return v + ' is my name';
});
schema.set('toObject', { getters: true });
var M = mongoose.model('Person', schema);
var m = new M({ name: 'Max Headroom' });
console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
  • toJSON: 该是和toObject一样的使用. 通常用来把 documents 转化为Object. 但是, 需要显示使用toJSON()方法,
var schema = new Schema({ name: String });
schema.path('name').get(function (v) {
return v + ' is my name';
});
schema.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' }
// since we know toJSON is called whenever a js object is stringified:
console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }

Model

model的创建

model的创建实际上就是方法的copy. 将schema上的方法,copy到model上. 只是copy的位置不一样, 一部分在prototype上, 一部分在constructor中.

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

这里,我们一定要搞清楚一个东西. 实际上, mongoose.model里面定义的第一个参数,比如’Tank’, 并不是数据库中的, collection. 他只是collection的单数形式, 实际上在db中的collection是’Tanks’.

想两边名称保持一致,可参考http://aiilive.blog.51cto.com/1925756/1405203

model 的子文档操作

本来mongodb是没有关系的. 但是, mongoose提供了children字段. 让我们能够轻松的在表间建立关系. 现在,我们来创建一个子域:

var childSchema = new Schema({ name: 'string' });

var parentSchema = new Schema({
children: [childSchema] //指明sub-doc的schema
});
//在创建中指明doc
var Parent = mongoose.model('Parent', parentSchema);
var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
parent.children[0].name = 'Matthew';
parent.save(callback);

现在, 我们就已经创建了3个table. 一个parent 包含了 两个child 另外,如果我们想要查询指定的doc。 则可以使用 id()方法.

var doc = parent.children.id(id);

子文档的CRUD, 实际上就是数组的操作, 比如push,unshift,remove,pop,shift等

parent.children.push({ name: 'Liesl' });

mongoose还给移除提供了另外一个方法–remove:

var doc = parent.children.id(id).remove();

如果你忘记添加子文档的话,可以在外围添加, 但是字段必须在Schema中指定

var newdoc = parent.children.create({ name: 'Aaron' });

document的CRUD操作

document 的创建 关于document的创建,有两种方法, 一种是使用document实例创建,另外一种是使用Model类创建.

document的创建

var Tank = mongoose.model('Tank', yourSchema);

var small = new Tank({ size: 'small' });
//使用实例创建
small.save(function (err) {
if (err) return handleError(err);
// saved!
}) //使用Model类创建
Tank.create({ size: 'small' }, function (err, small) {
if (err) return handleError(err);
// saved!
})

document的查询

Mongoose查找文档很容易,它支持MongoDB的丰富的查询语法。 可以使用每个models findfindByIdfindOnewhere 等静态方法进行查找文档。
事实上,在mongoose中,query数据 提供了两种方式.

  • callback: 使用回调函数, 即, query会立即执行,然后返回到回调函数中.
Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
if (err) return handleError(err);
// get data
})
  • query: 使用查询方法,返回的是一个Query对象. 该对象是一个Promise, 所以可以使用 chain 进行调用.最后必须使用exec(cb)传入回调进行处理. cb 是一个套路, 第一个参数永远是err. 第二个就是返回的数据。
Tank.find({ size: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

以下两种等价写法:

// With a JSON doc
Person.
find({
occupation: /host/,
'name.last': 'Ghost',
age: { $gt: 17, $lt: 66 },
likes: { $in: ['vaporizing', 'talking'] }
}).
limit(10).
sort({ occupation: -1 }).
select({ name: 1, occupation: 1 }).
exec(callback); // Using query builder
Person.
find({ occupation: /host/ }).
where('name.last').equals('Ghost').
where('age').gt(17).lt(66).
where('likes').in(['vaporizing', 'talking']).
limit(10).
sort('-occupation').
select('name occupation').
exec(callback);

Query Helpers

你能够添加 query helper functions,跟定义在Schema实例方法一样,但是返回query对象作为mongoose queries使用(说句白了就是封装mongoose查询方法). Query helper methods 使你能够扩展mongoose's chainable query builder API.

animalSchema.query.byName = function(name) {
return this.find({ name: new RegExp(name, 'i') });
}; var Animal = mongoose.model('Animal', animalSchema);
Animal.find().byName('fido').exec(function(err, animals) {
console.log(animals);
});

上面4个API, 3个使用方式都是一样的, 另外一个不同的是where. 他一样是用来进行query. 只是,写法和find系列略有不同.

where简介 where的API为: Model.where(path, [val]) path实际上就是字段, 第二个参数.val表示可以用来指定,path = val的数据内容, 你也可以不写, 交给后面进行筛选. 看一下对比demo吧:

User.find({age: {$gte: 21, $lte: 65}}, callback);
//等价于:
User.where('age').gte(21).lte(65).exec(callback);

从上面的query中,我们可以看到有许多fn, 比如gte,lte,$gte,$lte. 这些是db提供给我们用来查询的快捷函数. 我们可以参考, mongoose给的参考: query Helper fn

另外还有一些游标集合的处理方法: 常用的就3个, limit,skip,sort.

limit:用来获取限定长度的内容.

query.limit(20); //只返回前20个内容

skip: 返回,跳过指定doc后的值.

query.skip(2);

sort: 用来设置根据指定字段排序. 可以设置为1:升序, -1:降序.

query.sort({name:1,age:-1});

实际上, 关于query,我们需要了解的也就差不多了.

document删除

reomve操作仅在通过回调时执行。 要强制执行没有回调,您必须先调用remove(),然后使用exec()方法执行它。
我们可以在document上执行remove方法也可以在Model上。

Model.find().remove({ name: 'Anne Murray' }, callback)
Model.remove({ name: 'Anne Murray' }, callback)
//没有添加回调情况
Model.find().remove({ name: 'Anne Murray' }).remove(callback)
Model.remove({ name: 'Anne Murray' }).exce(callback)

document更新

使用Model.update([(conditions, doc, [options], [callback])]
不返回更新对象到应用程序。如果要更新数据库中的单个文档并将其返回到应用程序,请改用findOneAndUpdate。

参数说明:

  • conditions: 就是query. 通过query获取到指定doc
  • doc: 就是用来替换doc内容的值.
  • options: 这块需要说一些下.
    safe (boolean) 是否开启安全模式 (default for true)
    upsert (boolean) 如果没有匹配到内容,是否自动创建 ( default for false)
    multi (boolean) 如果有多个doc,匹配到,是否一起更改 ( default for false)
    strict (boolean) 使用严格模式(default for false)
    overwrite (boolean) 匹配到指定doc,是否覆盖 (default for false)
    runValidators (boolean): 表示是否用来启用验证. 实际上,你首先需要写一个验证. 关于如果书写,验证大家可以参考下文, validate篇(default for false)

new(使用findOneAndUpdate时才有参数):bool - 如果为true,则返回修改后的文档而不是原始文件。 默认为false。

Model.update({age:18}, { $set: { name: 'jason borne' }}, {multi:true}, function (err, raw) {
if (err) return handleError(err);
console.log('raw 就是mongodb返回的更改状态的falg ', raw);
//比如: { ok: 1, nModified: 2, n: 2 }
});

其中的$set是,用来指明更新的字段。

Validation

验证器在SchemaType中定义。
Validation 是一种中间件,Mongoose 触发 validation 同 a pre('save')钩子一样 。
你能够手动触发 validation 通过doc.validate(callback) or doc.validateSync()。

cat.save(function(error) {
//自动执行,validation
}); //手动触发 validatio
//上面已经设置好user的字段内容.
user.validate(function(error) {
//error 就是验证不通过返回的错误信息
assert.equal(error.errors['phone'].message,
'555.0123 is not a valid phone number!');
});
});

内置验证器

Mongoose 有一些列内置验证器.

  • 所有的SchemaTypes都有required验证器
  • min,max: 用来给Number类型的数据设置限制.
 var breakfastSchema = new Schema({
eggs: {
type: Number,
min: [6, 'Too few eggs'],
max: 12
}
});
  • enum,match,maxlength,minlength: 这些验证是给string类型的. enum 就是枚举,表示该属性值,只能出席那那些. match是用来匹配正则表达式的. maxlength&minlength 显示字符串的长度.
new Schema({
drink: {
type: String,
enum: ['Coffee', 'Tea']
},
food:{
type: String,
match:/^a/,
maxlength:12,
minlength:6
}
})

自定义验证器

如果内置验证器不够,您可以定义自定义验证器以满足您的需要。

// 创建验证器
function validator (val) {
return val == 'something';
}
new Schema({ name: { type: String, validate: validator }}); // 附带自定义错误信息 var custom = [validator, 'Uh oh, {PATH} does not equal "something".']
new Schema({ name: { type: String, validate: custom }}); //添加多验证器 var many = [
{ validator: validator, msg: 'uh oh' }
, { validator: anotherValidator, msg: 'failed' }
]
new Schema({ name: { type: String, validate: many }}); // 直接通过SchemaType.validate方法定义验证器: var schema = new Schema({ name: 'string' });
schema.path('name').validate(validator, 'validation of `{PATH}` failed with value `{VALUE}`');

验证错误对象

验证失败后返回的错误包含一个包含实际ValidatorError对象的错误对象。 每个ValidatorError都有kind,path,value和message属性。

  var toySchema = new Schema({
color: String,
name: String
}); var Toy = db.model('Toy', toySchema); var validator = function (value) {
return /blue|green|white|red|orange|periwinkle/i.test(value);
};
Toy.schema.path('color').validate(validator,
'Color `{VALUE}` not valid', 'Invalid color'); var toy = new Toy({ color: 'grease'}); toy.save(function (err) {
// err is our ValidationError object
// err.errors.color is a ValidatorError object
assert.equal(err.errors.color.message, 'Color `grease` not valid');
assert.equal(err.errors.color.kind, 'Invalid color');
assert.equal(err.errors.color.path, 'color');
assert.equal(err.errors.color.value, 'grease');
assert.equal(err.name, 'ValidationError');
});

更新验证器

在Model.update那一节有个参数–runValidators. 还没有详细说. 这里, 展开一下. 实际上, validate一般只会应用在save上, 如果你想在update使用的话, 需要额外的trick,而runValidators就是这个trick.
Mongoose还支持update()和findOneAndUpdate()操作的验证。 在Mongoose 4.x中,更新验证器默认关闭 - 您需要指定runValidators选项。

var opts = { runValidators: true };
Test.update({}, update, opts, function(error) { //额外开启runValidators的验证
// There will never be a validation error here
});

更多验证器用法请参考官方文档

population

ongodb 本来就是一门非关系型数据库。 但有时候,我们又需要联合其他的table进行数据查找。 mongoose提供的 population. 用来连接多表数据查询. 一般而言, 我们只要提供某一个collection的_id , 就可以实现完美的联合查询. population 用到的关键字是: ref 用来指明外联的数据库的名字. 一般,我们需要在schema中就定义好.

var mongoose = require('mongoose')
, Schema = mongoose.Schema var 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);

Note: ObjectId, Number, String, and Buffer are valid for use as refs.

使用populate query方法进行关联

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"
});

中间件

mongoose里的中间件,有两个, 一个是pre, 一个是post.

  • pre: 在指定方法执行之前绑定。 中间件的状态分为 parallel和series.
  • post: 相当于事件监听的绑定

这里需要说明一下, 中间件一般仅仅只能限于在几个方法中使用. (但感觉就已经是全部了)

  • doc 方法上: init,validate,save,remove;
  • model方法上: count,find,findOne,findOneAndRemove,findOneAndUpdate,update

pre

我们来看一下,pre中间件是如何绑定的.

串行

var schema = new Schema(..);
schema.pre('save', function(next) {
// do stuff
next(); //执行完毕,执行下一中间件
});

并行

var schema = new Schema(..);

// 设置第二参数为true,意味这是一个并行中间件
// as the second parameter if you want to use parallel middleware.
schema.pre('save', true, function(next, done) {
// calling next kicks off the next middleware in parallel
next();
setTimeout(done, 100);
});

post

post会在指定事件后触发,就像事件监听器一样,post钩子没什么控制流程,即它是异步的。

schema.post('save', function(doc) {
//在save完成后 触发.
console.log('%s has been saved', doc._id);
});

当save方法调用时, 便会触发post绑定的save事件.
假如你绑定了多个post。 也可以需要指定一下中间件顺序.

// Takes 2 parameters: this is an asynchronous post hook
schema.post('save', function(doc, next) {
setTimeout(function() {
console.log('post1');
// Kick off the second post hook
next();
}, 10);
}); // Will not execute until the first middleware calls `next()`
schema.post('save', function(doc, next) {
console.log('post2');
next();
})

Mongoose初使用总结的更多相关文章

  1. [转] Mongoose初使用总结

    连接mongoose mongoose连接数据库有两种方式 第一种: 'use strict'; const mongoose = require('mongoose'); mongoose.conn ...

  2. 深入浅出mongoose

    深入浅出mongoose mongoose是nodeJS提供连接 mongodb的一个库. 此外还有mongoskin, mongodb(mongodb官方出品). 本人,还是比较青睐mongoose ...

  3. [转] 深入浅出mongoose-----包括mongoose基本所有操作,非常实用!!!!!

    深入浅出mongoose mongoose是nodeJS提供连接 mongodb的一个库. 此外还有mongoskin, mongodb(mongodb官方出品). 本人,还是比较青睐mongoose ...

  4. koa2搭建服务器+使用mongoose链接mangodb

    使用node搭建服务器,用到了现在比较流行的框架koa. 1.初始化package.json npm init -y 2.安装koa2 npm i koa --save 3.搭建服务器 const K ...

  5. .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验

    不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...

  6. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

  7. Spring之初体验

                                     Spring之初体验 Spring是一个轻量级的Java Web开发框架,以IoC(Inverse of Control 控制反转)和 ...

  8. 【初码干货】使用阿里云对Web开发中的资源文件进行CDN加速的深入研究和实践

    提示:阅读本文需提前了解的相关知识 1.阿里云(https://www.aliyun.com) 2.阿里云CDN(https://www.aliyun.com/product/cdn) 3.阿里云OS ...

  9. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

随机推荐

  1. 使用wkwebview时,push后,再pop返回,报错

    使用wkwebview时,push后,再pop返回,报错 Cannot form weak reference to instance (xxxx) of class xxxx. It is poss ...

  2. left join 和inner join关联查询区别

    inner join 必须两边对应才能查处结果 left join 用主表关联副表,关联不出来依然显示结果

  3. rsync同步本地和服务器之间的文件

    同步本地文件到服务器 rsync -zvrtopg --progress --delete test -e 'ssh -p 6665' yueyao@172.16.0.99:/media/sdb/us ...

  4. 怎样ubuntu下命令行终端显示短路径

    参考:http://blog.sina.com.cn/s/blog_b71132f001016cmm.html ubuntu的终端命令行默认是长路径,即把路径深度全部显示出来,操作起来不是很方便,下面 ...

  5. Hue,Oozie运行sqoop找不到驱动解决办法

    一.前言 平台:CDH 5.13.0 公司在客户那边有个项目需要部署cloudera平台,部署的时候,在这个版本的cdh中,除了基本组件,还选了sqoop2作为数据传输工具,希望能在Oozie中通过工 ...

  6. 【工具】java发送验证码邮件

    文章目录 前言 配置邮箱服务器 代码实现 发送随机验证码与验证 后记 前言 要实现 可以设置格式,附件,抄送等功能,就跟真人操控邮箱发送邮件一样的功能,或许比较难,博主没研究,博主暂时没用到那些功能, ...

  7. 怎样获取当前页面框架的数量(即iframe和frame的数量)

    需要使用window.length, 或者window.frames.length; 如果页面中不包含frame和iframe元素, 则返回0; window.length === window.fr ...

  8. maven一些简单常用却容易记混的命令参数-U -e -B

    install 命令完成了项目编译.单元测试.打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库,但没有布署到远程Maven私服仓库: deploy 命令完成了项目 ...

  9. axios拦截登陆过期请求多次

    request.interceptors.response.use( response => { console.log(response.data.code) // console.log(r ...

  10. ios下按钮click事件点击穿透问题

    和app进行混合开发的时候,一个页面使用h5写的,按钮上绑定click事件会触发下面图片上的a链接导致跳转,页面如图 顶部是一个banner,分vr.视频.图片三部分,红框处的三个nav按钮绑定cli ...