Linux001基本命令

linux的文件目录

linux里没有盘符的概念(也就是没有windows里的cdef盘)它不分盘

  • 它有一个顶层目录叫做根目录 「/」斜杠
  • 它的目录像一棵树
1
2
3
4
5
6
7
8
9
10
-|/
-|/bin
-|/sbin
-|/usr
-|/usr/bin
-|/usr/local
-|/usr/local/include
-|/usr/lib
-|/lib
-|/...
1
2
3
4
5
cd / 
linux中 / 代表根目录

cd ~
linux中 ~代表用户名录

linux里常用的文件夹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/home 系统默认的用户家目录(也就是你可以随意操作的目录)最常用的目录

/home 下的每一个文件夹代表的用户

/home/xxx 张三目录
/home/yyy 李四目录

/home/xxx/ 又会有一些文件夹

Desktop(桌面)
Downloads(下载相关的)


/bin 不要随意操作(可运行命令的执行环境)
/usr/bin 也不要随意操作(可运行命令的执行环境)
/usr 存放用户的应用程序
/tmp 临时性的文件(比如垃圾文件)
/dev 和设备相关的(比如你插的U盘)

linux常用命令

ls 显示当前路径下的东西

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ls -l 按行显示文件及目录(不包含隐藏文件)
ls -a 显示所有文件(包含隐藏的文件)
ls -al 按行显示所有文件及详细信息
ls -h 代表文件大小(多少k)

-l后显示形如
drwxr-xr-x 1 hjx hjx 197121 0 Apr 9 23:35 public
-rw-r--r-- 1 hjx hjx 197121 76850 Mar 23 22:23
yarn.lock

drwxr-xr-x 代表 一共十位 从第二位开始 后九个代表权限
-rw-r--r-- 代表 一共十位 从第二位开始 后九个代表权限

第一个字母代表文件
第一个字母
d 代表目录
- 代表普通文件

1 代表链接数
第一个 hjx代表当前用户
第二个 hjx代表用户组

查看 Desktop目录里的东西

1
2
# 大前提是你在 Desktop的父目录
ls Desktop

区分绝对路径和相对路径

1
2
3
4
5
6
7
8
9
10
11
绝对路径 cd /home/aaa
相对路径 cd Desktop

. 表示当前路径
.. 表示当前路径的上一层
../.. 表示当前路径的上一层的上一层
cd ..

cd - 跳转到上一次所在的路径(只在最近两次的目录直接进行直接跳转)

cd Music 等价于 cd ./Music

cd 切换目录

1
2
3
4
cd 「跳转的目录」
cd ~ 切换到当前用户目录
cd / 切换到根目录
cd .. 回到上一级目录(父目录)

pwd 显示当前路径(从头到尾)

1
pwd 当前目录的绝对路径从头到尾

clear 清屏

tab自动补全

1
2
3
4
5
# 比如你在你的用户目录   里面有 Desktop 和 Downloads

cd D 按tab 不会进行自动补全(因为存在两个开头一样的D目录)

cd De 按 tab 就能自动补全

touch创建文件

1
touch 1.txt

正则相关的操作

问题1 显示当前路径下所有的 .txt文件

1
ls *.txt

问题2 显示当前目录下有.txt .tnt .tst

1
ls *.t?t

问题3 显示 当前目录下的 .txt .tnt文件

1
ls *.t[nx]t
1
2
3
4
5
6
7
? 代表一个字符有且仅有,不能没有
[xn] 代表括号里任意一个字符
[abcdef] 可以写为 [a-f] 表示a到f的任意字符

如果有以下文件恰好叫 1a 2a 3a *a
ls *a就会有歧义 会显示 1a 2a 3a *a
ls \*a 转义 会显示 *a

重定向 >

1
2
3
4

ls > 1.txt 文件不存在就创建,清空1.txt的内容 把ls显示的内容填充到1.txt里

ls >> 1.txt 文件不存在就创建,不清空1.txt的内容 把ls的内容追加到1.txt

分屏 more

用命令查看文件的内容

1
more 1.txt  如果文件内容超过一屏显示  就按当前内容所占比例显示在下方   按空格进行查看其余内容

管道 |

一行里写多个命令通常不好使此时就需要使用管道了

1
ls -alh | more

mkdir创建目录

1
2
3
4
5
# 当前目录创建一个demo文件夹
mkdir demo

# 当前目录创建 a/b/c 嵌套目录的文件夹 需要添加 -p
mkdir -p a/b/c

tree 以目录树的方式显示目录结构

rmdir删除目录

1
2
3
rmdir demo

# 无法删除嵌套目录 如 demo/a/b

rm 删除文件(慎用)

1
2
3
4
5
6
7
8
rm / 千万不要用,你就完蛋了从根目录开始删
rm / 千万不要用,你就完蛋了从根目录开始删
rm / 千万不要用,你就完蛋了从根目录开始删

rm 文件名
rm -f 强制删除,也就是不提示(你确认删除吗?)
rm -r 目录 递归的删除目录(每删除一个文件问你一次 你确认删除吗?)
rm -rf 递归的删除目录(没有任何提示)

iview引入问题

本文针对vue-cli@2.9.3版本

我使用的iview版本为2.14.1

引入iview触发的问题

本地运行正常,打包后报错提示没有某个字体文件

webpack.prod.conf.js

1
2
3
4
5
6
7
8
9
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: false
// extract: true
})
}

//里边的 extract改为false,默认是true

详情请参考issues

iview全局引入后,打包体积过大

我说的是vendor.js(打包后的1M)

然后依照官网的api进行按需引用的改造

借助插件 babel-plugin-import可以实现按需加载组件,减少文件体积。首先安装,并在文件 .babelrc 中配置:

1
2
3
4
5
6
7
8
9
npm install babel-plugin-import --save-dev

// .babelrc
{
"plugins": [["import", {
"libraryName": "iview",
"libraryDirectory": "src/components"
}]]
}

然后这样按需引入组件,就可以减小体积了:

1
2
3
import { Button, Table } from 'iview';
Vue.component('Button', Button);
Vue.component('Table', Table);

但是这样会报UglifyJs的错误,因为截止2018年6月6日为止,iview里的内容使用了es6语法,然而uglifyJs是不支持的!

1
UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify

于是我就又各种搜索报错终于找到答案

原文链接

解决方案(参考以上链接)

  1. 在webpack.base.conf.js中,我们先在js编译的时候添加如下:
1
2
3
4
5
6
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'),
resolve('test'),resolve('/node_modules/iview/src'),resolve('/node_modules/iview/packages')]
}
  1. 先让iview的es6语法经过babel来转换,然后在build/webpack.prod.conf.js中,注释掉原来的uglifyJs,引入外部的uglifyJs对js进行压缩混淆,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//改动 你需要下载依赖 
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

// 注释掉原来的 UglifyJs 因为 它不支持ES6
// new webpack.optimize.UglifyJsPlugin({
// compress: {
// warnings: false
// },
// sourceMap: true
// }),
new UglifyJsPlugin({
// 使用外部引入的新版本的js压缩工具
parallel: true,
sourceMap: true,
uglifyOptions: {
ie8: false,
ecma: 6,
warnings: false,
mangle: true,
// debug false
output: {
comments: false,
beautify: false,
// debug true
},
compress: {
// 在UglifyJs删除没有用到的代码时不输出警告
warnings: false,
// 删除所有的 `console` 语句
// 还可以兼容ie浏览器
drop_console: true,
// 内嵌定义了但是只用到一次的变量
collapse_vars: true,
// 提取出出现多次但是没有定义成变量去引用的静态值
reduce_vars:true
}
}
}),
  1. 不要忘了安装依赖
1
cnpm install uglifyjs-webpack-plugin --save-dev
  1. 详情配置请参考官网

uglifyjs-webpack-plugin

经历如上步骤后,我的vendor.js打包后体积为 300K(我只用了iview 的 DatePicker)
但是iview即使按需引入css还是挺大的大约300K还需要在 main.js里引入 依然很大。。。。。。

vue多页面配置问题汇总

注意:本项目基于vue-cli 2.9.3

基于上一篇vue多页面的配置方式

很多时候我们需要引用同一模块

当你定义api接口的时候,或者加载去除默认样式的reset.css文件

我们应把复用的模块放在同一目录下,如图我这里把复用的文件放在「modules」里

找到webpack.base.conf.js文件,添加如下代码

1
2
3
4
5
6
7
8
9
10
11
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
// 公共文件路径加载
'css':'@/modules/css',
'js':'@/modules/js',
'components':'@/components'
}
}

当你的页面里需要使用该模块的时候就可以像这样引入

1
2
import 'css/reset.css';
import 'js/flexible.js';

引入淘宝移动端适配方案后flexible.js 与引入 mint-ui的冲突

当你做了移动端适配后,也就是配置了postcss-px2rem后,引入mint-ui框架会把UI框架里组件像素单位「px」转为「rem」

我使用的是postcss依赖 所以.postcssrc.js配置如下

1
2
3
4
5
6
7
8
9
module.exports = {
"plugins": {
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {},
"postcss-px2rem": {
remUnit: 75
}
}
}

移动端如果使用阿里的flexible适配方案,现有的移动端UI库大部分都不适用了,移动端的UI库默认的initial-scale=1,在高清屏上flexible会调整initial-scale=1/dpr,UI的样式被整体缩小了

这样就导致UI变形
  • 解决方式一:就是你要用样式覆盖,这样就更恶心了
  • 解决方式二:依然使用flexible适配方案,但是不使用px2rem

注掉使用postcss-px2rem的功能,采用手写rem的方式,这样引入的ui组件样式就不会变小

1
2
3
4
5
6
7
8
9
module.exports = {
"plugins": {
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {},
//"postcss-px2rem": {
// remUnit: 75
//}
}
}

手写rem问题来了,又回到原始的方式了

我们可以使用强大的IDE插件来帮我们解决问题

我用的是VScode,设计稿750px,如果每个需要适配的单位都去计算rem是很麻烦的,推荐px to rem这个插件,然后将16设置为75(设计稿为750px)

这个时候我们直接写px,选中后alt+z就直接转换为rem了

  • 先选中如下文本 「16px」
  • 再按住「alt」
  • 最后按「z」

npm run build问题

打包之后的文件为绝对路径,需在服务环境下才能打开

不方便我们本地调试,我们需要相对路径

  1. 打开config文件夹下的index.js文件
  2. 修改build中assetsPublicPath为’’(原本为’/‘)

静态资源路径问题

1
2
3
4
-|src
-|static
---|img
------|aa.png
在html或者css里请这样书写,打包后这个路径也是对的
1
<img src="static/img/aa.png">

注意这样是错的

1
../../static/img/aa.png

web性能优化之DNS预解析

DNS预解析

去参考淘宝的移动端页面你可能会看到这样一段代码

请自行选择

淘宝

1
2
3
4
5
6
7
8
<title>淘宝网触屏版</title>
<meta name=data-spm content=a215s>
<link rel="dns-prefetch" href="//g.alicdn.com">
<link rel="dns-prefetch" href="//gw.alicdn.com">
<link rel="dns-prefetch" href="//log.mmstat.com">
<link rel="dns-prefetch" href="//api.m.taobao.com">
<link rel="dns-prefetch" href="//cdn.tanx.com">
<link rel="dns-prefetch" href="//ecpm.tanx.com">
  • 淘宝页面有很多的图片资源

预解析就是指「加载后面图片的时候,不会对域名再次进行解析了(因为已经解析过了)」

作用

  • 加快后面图片的解析时间

待更新

vue多页面配置方式

注意本文使用的vue-cli是2.9.3

vue多页面配置调整方式

  1. 全局安装vue-cli
1
npm install vue-cli@2.9.3 -g
  1. 生成模板,我使用的模板是webpack
1
vue init webpack xxx
  1. 安装过程中的询问
  • 是否安装vue-router(安装方便我们多页面里路由再次进行跳转)
  • 是否安装eslint (这个配置比较繁琐这次不安装)
  • 后面几个模块先不进行安装(这次的目标是多页面配置。。。。)

初始化后会有提示如何进行运行

1
2
3
4
# 依照我们的项目,你应该
cd xxx //切换到生成的模板目录
npm install //安装依赖
npm run dev //如果出现经典的vue logo说明你初始化成功
  1. 多页面的目录结构调整

  • 在开发路径src下增加modules和pages文件夹,分别存放模块和页面
  • 页面的所有文件都放到同一文件夹下就近管理:
  • 如上选中文件都移到index文件夹下,并把main.js改为index.js,保证页面的入口js文件和模板文件的名称一致
    1
    2
    3
    4
    index.html(页面模板)
    main.js(页面入口文件)
    App.vue(页面使用的组件,公用组件放到components文件夹下)router(页面的路由配置)
    assets(页面的静态资源)
  1. 添加共同方法
  • 在build/utils.js中添加两个方法:webpack多入口文件和多页面输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
var glob = require('glob')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var PAGE_PATH = path.resolve(__dirname, '../src/pages')
var merge = require('webpack-merge')

//多入口配置
exports.entries = function() {
var entryFiles = glob.sync(PAGE_PATH + '/*/*.js')
var map = {}
entryFiles.forEach((filePath) => {
var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
map[filename] = filePath
})
return map
}

//多页面输出配置
exports.htmlPlugin = function() {
let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
let arr = []
entryHtml.forEach((filePath) => {
let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
let conf = {
template: filePath,
filename: filename + '.html',
chunks: [filename],
inject: true
}
if (process.env.NODE_ENV === 'production') {
conf = merge(conf, {
chunks: ['manifest', 'vendor', filename],
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
})
}
arr.push(new HtmlWebpackPlugin(conf))
})
return arr
}
  1. 修改配置

1) 修改build/webpack.base.conf.js的入口配置

1
2
3
4
5
// 替换默认的单页面入口
// entry: {
// app: './src/main.js'
// }
entry: utils.entries()

2)修改build/webpack.dev.conf.js和build/webpack.prod.conf.js的多页面配置:

把原有的页面模板配置注释或删除,并把多页面配置添加到plugins

webpack.dev.conf.js:

1
2
3
4
5
6
7
8
9
plugins: [
......
// new HtmlWebpackPlugin({
// filename: 'index.html',
// template: 'index.html',
// inject: true
// }),
......
].concat(utils.htmlPlugin())

webpack.prod.conf.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
plugins: [
......
// new HtmlWebpackPlugin({
// filename: config.build.index,
// template: 'index.html',
// inject: true,
// minify: {
// removeComments: true,
// collapseWhitespace: true,
// removeAttributeQuotes: true
// },
// chunksSortMode: 'dependency'
// }),
......
].concat(utils.htmlPlugin())
  1. 在pages目录里创建cart目录
  • 新建cart.html
  • 新建cart.js

  1. 终于你可以试试多页面是否成功了
1
npm run dev

补充说明

在上面多页面输出配置utils.js中有这样一行代码:

1
chunks: ['manifest', 'vendor', filename]

这是html-webpack-plugin插件对页面入口文件(即js文件)的限定,如果不设置则会把整个项目下的所有入口文件全部引入

  • 为什么要引入’manifest’和’vendor’

在build/webpack.prod.conf.js中有如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
}),
  • vendor模块是指提取涉及node_modules中的公共模块
  • manifest模块是对vendor模块做的缓存

关于CommonsChunkPlugin插件的详细说明请阅读官方文档

关于html-webpack-plugin插件的配置还有一行代码:

1
chunksSortMode: 'dependency'

插件会按照模块的依赖关系依次加载,即:manifest,vendor,本页面入口,其他页面入口…

至此,多页面应用已经搭建完毕,只需要在pages文件夹创建相应的页面文件即可。

Schema和Model

我使用的mongodb是 4.11.4

Schema

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const mongoose = require('mongoose');
const uri = 'mongodb://localhost/test';
mongoose.connect(uri);
const db = mongoose.connection;

const Schema = mongoose.Schema;


// 创建Schema模式对象
const UserSchema = new Schema({
name:String,
age:Number
})

/*
1.通过Schema创建Model
Model代表 数据库中的集合collections
mongodb命令行里使用要加s 如 db.users.find()
2. mongoose.model(集合名称,模型对象)
*/
const UserModel = mongoose.model('user',UserSchema);

db.on('open',()=>{console.log('db open ')})
db.on('error',(err,res)=>{console.log('db error')})
db.on('close',(err,res)=>{console.log('db close')})

运行如上代码数据库连接成功后 mongodb中并不会立刻创建 collection,需要向数据库中插入文档才会创建

1
2
3
4
5
6
7
8
UserModel.create({
name:'hjx',
age:18
},function(err){
if(!err){
console.log("创建成功")
}
})

Schema模型对象的规则约束

1
2
3
4
5
6
7
8
9
10
11
12
13
const UserSchema =Schema({
// type:类型
// require 是否必须
// unique 在mongodb里创建索引 类似mysql唯一主键
// enum:['aa','bb'] 指定他的值必须是什么
name:{type:String,require:true,unique:true,enum:['hjx','lisi']},
// 最简单写法
// age:Number
// 数字复杂的校验
// max 最大值
// min 最小值 如果是数组 第一个值是最小范围 第二个值是报错信息
age:{type:Number,max:90,min:[18,'不能小于18岁']}
})

Model

把全局的Pormise挂载到 mongoose.Promise上

使用 async、await解决异步问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const mongoose = require('mongoose');
const uri = 'mongodb://localhost/test';
mongoose.connect(uri);
const db = mongoose.connection;
const Schema = mongoose.Schema;

mongoose.Promise = global.Promise;

// 表单对象
const UserSchema =new Schema({
name:String,
age:Number
})

const UserModel = mongoose.model('user',UserSchema);

(async()=>{
let created = await UserModel.create({
name:'hjx',
age:18
}).then()
return created;
})().then(r=>{
console.log(r)
}).catch(e=>{

})

db.on('open',()=>{console.log('db open ')})
db.on('error',(err,res)=>{console.log('db error')})
db.on('close',(err,res)=>{console.log('db close')})

实例方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
const UserSchema = new Schema({
name:String,
age:Number
})

const UserModel = mongoose.model('user',UserSchema);
// 实例方法
UserSchema.methods.sayYourName = function(){
return this.name;
}
// 静态方法
UserSchema.statics.findByName = async function(name){
return await this.findOne({name:name})
}

// 具体的表 命令行里使用要加s 如 db.users.find()
const UserModel = mongoose.model('user',UserSchema);

// 实例方法
(async()=>{
let found = await UserModel.findOne({});
console.log(found.sayYourName())
})().then(r=>{
console.log(2)
}).catch(e=>{

})

// 静态方法
(async()=>{
let found = await UserModel.findByName('hjx');
return found;
})().then(r=>{
console.log(r)
}).catch(e=>{

})

//保存
(async()=>{
let user = new UserModel({name:'lisi',age:19})
return await user.save()
})().then(r=>{
}).catch(e=>{
console.log(e)
})

工厂模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 工厂模式
(async(params)=>{
let flow = UserModel.find({});
flow.where('age').lt(21);
flow.select({name:1})
flow.skip(0);
if(params.sort) flow.sort(params.sort);
let res = await flow.then()
return res;
})({
sort:'-age'
})
.then(r=>{
console.log(r)
})
.catch(e=>{
console.log(e)
})

mongoose是什么鬼

什么是mongoose

在之前的文章中我们都是命令行操作mongodb

  • 而实际使用中肯定不能让客户操作命令行录入数据
  • mongoose是一个可以让我们通过node来操作 mongoDB的模块
  • mongoose是一个ODM库(对象文档模型)

官网

moogoose实际作用是让我们以「对象的形式」操作数据库

好处

  1. 可以为文档创建一个模式结构(Schema)
  2. 可以对模型中的对象进行验证
  3. 数据可以通过类型转换为对象模型
  4. 可以使用中间件来与业务逻辑挂钩
  5. 比Node原生的mongodb驱动更容易

mongoose提供的对象

  • Schema (模式对象) 对字段进行约束
  • Model 作为集合中所有文档的表示,相当于MongoDB中的collections
  • Document 表示集合中的具体文档,相当于MongoDB中的document

使用mongoose

  1. 下载安装 mongoose
1
2
3
4
5
6
7
8
9
10
# 创建项目目录
mkdir demo
# 切换目录
cd demo
# 初始化package.json
npm init 一路回车
# 安装依赖
npm i mongoose --save
# 新建test.js
touch test.js
  1. 引入mongoose
1
const mongoose = require('mongoose')
  1. 连接数据库

如果端口号是27017可以省略

1
2
3
//引入mongoose模块
const mongoose = require('mongoose')
mongoose.connect("mongodb://数据库的ip地址:端口号/数据库名")
  1. 监听数据库的连接状态
1
mongoose.disconnect() //一般不使用

全部代码

1
2
3
4
5
const mongoose = require('mongoose');
const db = mongoose.connect('mongodb://localhost/test');
db.on('open',()=>{console.log("数据库连接成功")})

db.on('close',()=>{console.log("数据库连接断开")})

和mysql区别

  • mongoDB一般只连接一次,不会主动断开(没有事务控制)除非服务器宕机
  • mysql是关系型数据库,每操作数据就要进行事务控制,以至于 连接一次关闭一次 连接一次关闭一次

所以一般不会调用 mongoose.disconnect()

mongoDb练习三

练习3

  1. 查询工资小于1000 或 大于3000的数据
1
2
3
4
5
6
7
8
9
10
db.emp.find({
$or:[
sal:{
$lt:1000
},
sal:{
$gt:3000
}
]
})
  1. 为所有工资低于1000的 员工 涨薪 400
1
2
3
4
db.emp.updateMany(
{sal:{$let:1000}},
{$inc:{sal:400}}
)

排序 sort()

查询文档时,默认按_id的值进行升序排列

  • sort()需要传递一个对象指定对应列进行排序
  • 1代表升序
  • -1代表降序
  • 多个排序 sort({sal:1,empno:-1}) 先按照工资排序 然后再按照 部门排序
  • limit skip sort 可以任意顺序调用
1
2
3
4
按工资升序排列
db.emp.find({}).sort({sal:1})
按工资降序排列
db.emp.find({}).sort({sal:-1})

设置投影 (如果我只想看员工姓名/工资,不想看_id)

1
db.emp.find({},{name:1,sal:1,_id:0})

mongoDb文档之间的关系

文档之间的关系

一对一 one to one

  • 夫妻
  • Mongodb中 通过内嵌文档体现 一对一的关系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
db.test.insert([
{
name:"黄蓉",
husband:{
name:"郭靖"
}
},
{
name:"小龙女",
husband:{
name:"杨过"
}
}
])

一对多 one to many / many to one

  • 父母 孩子
  • 用户 订单
  • 文章 评论

一对多的关系 ==> 用户&&订单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
db.users.insert([
{username:"aaa"},
{username:"bbb"}
])

/*
{_id:ObjectId("5aaaaaaaaaaaaaa"),username:"aaa"},
{_id:ObjectId("5bbbbbbbbbbbbbb"),username:"bbb"}
*/

订单
db.order.insert({
list:["苹果","香蕉","葡萄"]
user_id:ObjectId("5aaaaaaaaaaaaaa")
})

db.order.insert({
list:["华为","平板","iPad"]
user_id:ObjectId("5bbbbbbbbbbbbbb")
})

查询用户名 aaa的订单
var aaaId = db.users.find({username:"aaa"})
db.order.find({user_id:aaaId})

多对多 many to many

  • 分类 商品
  • 老师 学生
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
db.teachers.insert([
{name:"欧阳锋"},
{name:"黄药师"},
{name:"洪七公"}
])

db.students:insert([
{
name:"郭靖",
tech_ids:[
ObjectId("5aaaaaaaaaaa"),
ObjectId("5bbbbbbbbbbb"),
ObjectId("5ccccccccccc"),
]
},
{
name:"孙悟空",
tech_ids:[
ObjectId("5aaaaaaaaaaa"),
ObjectId("5bbbbbbbbbbb")
]
}
])

使用最广泛的关系是 一对多

mongoDb练习二

练习2

  1. 向 numbers 集合中插入20000条数据

笨方法

1
2
3
4
5
6
db.numbers.insert({num:1})
db.numbers.insert({num:2})
db.numbers.insert({num:3})
db.numbers.insert({num:4})
...
db.numbers.insert({num:20000})

稍微快一点

1
2
3
for(var i=1;i<=20000,i++){
db.numbers.insert({num:i})
}

快一点

1
2
3
4
5
6
var arr =[];
for(var i=1;i<=20000,i++){
arr.push({num:i})
}

db.numbers.insert(arr)
  1. 查询numbers 中 num 为500的文档
1
db.numbers.find({num:500})
  1. 查询 num 大于500的文档

$lt 小于 $gt大于 $eq等于 $ne 不等于

1
db.numbers.find({num:{$gt:500}})
  1. 查询 num 大于等于500的文档
1
db.numbers.find({num:{$gte:500}})
  1. 查询num 大于40 小于50的文档
1
db.numbers.find({num:{$gt:40,$lt:50}})
  1. 查看 numbers集合中 前10条数据

limit()设置数据的上限

1
2
3
4
5
6
不靠谱的方式
db.numbers.find({num:{$lte:10}})

靠谱的方式
设置显示数据的上限
db.numbers.find().limit(10)

开发中绝对不该执行不带条件的查询

1
db.numbers.find()
  1. 查询numbers 11条到20条的数据

分页skip()

1
2
3
4
5
1-10
11-20
21-30
...
skip()用于跳过指定的条数
1
db.numbers.find().skip(10).limit(10)
  1. 查询numbers 21条到30条的数据
1
db.numbers.find().skip(20).limit(10)

分页公式

1
skip((pageNo-1)*pageSize).limit(pageSize)

注意事项

1
2
mongodb会自动调整 skip和limit的位置
skip() 和 limit()的顺序谁先谁后无所谓