Hexo安装使用

安装

一、hexo安装

    $ npm install -g hexo-cli

    $ hexo init

    $ npm install

    $ hexo generate            生成静态文件

    $ hexo server            启动服务器


二、github创建项目

    github创建项目并取到ssh路径

三、配置_config.yml

    根目录打开_config.yml,修改下面内容

    theme: concise            // 接下来安装主题的名称

    deploy:
        type: git
        repo: https://github.com/siguang1983/siguang1983.github.io.git
        branch: master

四、安装主题

    https://hexo.io/themes/            选择一个主题

    安装主题每个主题都会有安装的介绍 

    主题安装会在themes目录下,删除其它主题如果不删除还上传后还会显示之前的主题

    设置主题的样式也在这里

命令

$ hexo clean

$ hexo d -g         根据设置的deploy中repo的地址发布到github上

文档放到source/_posts目录下

| https://hexo.io/zh-cn/

前端插件收集

前端开发桌面程序

1、Electron - https://electronjs.org/docs                可以开发.exe的桌面程序

    https://www.jianshu.com/p/57d910008612

UI框架

一、Bootstrap中文网:http://www.bootcss.com/       

二、Bootstrap Table API:  http://bootstrap-table.wenzhixin.net.cn/zh-cn/getting-started/

        http://www.cnblogs.com/gamehiboy/p/5176618.html

三、Vue UI:

    1、layUI框架: http://www.layui.com/

        页面中加载layui
        <script src="lib/layui.js"></script>
        <script src="mian.js"></script>

        main.js
        layui.use(['laydate'], function(){         // laydate 调用日期插件
                var laydate = layui.laydate;
                var oD = document.getElementById("dateInput");

                var start = {
                elem: oD,
                min: laydate.now(),
                max: '2099-06-16 23:59:59',
                istoday: false,
                choose: function(datas){
                    end.min = datas;     // 开始日选好后,重置结束日的最小日期
                    end.start = datas     // 将结束日的初始值设定为开始日
                }
            };

            laydate(start);          
        });

    饿了么vue PC端框架 : http://element.eleme.io/#/zh-CN/resource

四、React UI:

    蚂蚁金服React ui框架https://ant.design/

    react native https://github.com/ant-design/ant-design-mobile/blob/master/README.zh-CN.md

                    https://mobile.ant.design/docs/react/introduce

    React UI: http://rsuite.github.io/#/?_k=1me3ji

    React 图表: BizCharts:http://bizcharts.net/products/bizCharts/demo

微信UI

UI库 http://vue.ydui.org/

移动端UI

阿里移动端框架 mui: http://m.sui.taobao.org/

饿了么vue ui移动框架: http://mint-ui.github.io/#!/zh-cn

flexible移动端rem转换: http://caibaojian.com/flexible-js.html

JS库

1、jQeruy

2、underscore: http://www.css88.com/doc/underscore/

3、zepto: http://www.bootcss.com/p/zeptojs/


日期类

1、jquery DateTimePicker:  http://www.jq22.com/jquery-info332

2、Bootstrap DataPicker:   http://www.bootcss.com/p/bootstrap-datetimepicker/

3、laydate:  http://laydate.layui.com/

JS框架

1、VueJS

2、AngularJS    

vue-strap:http://yuche.github.io/vue-strap/

3、React

4、ReactNative

Mock数据

1、mock:http://mockjs.com/       // 生成随机数据,拦截 Ajax 请求

2、RAP: http://rap.taobao.org/org/index.do

    复制一个字段名,然后新建一个字段粘贴,在按ctrl+回车,就会将他下面所有的数据都复制过来,对于层级很复杂的比较好用

chrome 插件

    EditThisCookie   设置cookie

    PostMan        post请求

3、在线编辑代码: https://jsfiddle.net/

NodeJS

Exporess:  http://www.expressjs.com.cn/

egg阿里nodejs框架:https://eggjs.org/zh-cn/basics/middleware.html

移动端的Sass框架

yo: https://github.com/doyoe/Yo#bugs-and-feature-requests

icons

http://www.iconfont.cn/                    // 阿里图标收集

http://www.fontawesome.com.cn/

https://icons8.com/icon/new-icons/all

http://emojipedia.org/    小图片

其它插件

1、socket: https://github.com/sockjs/sockjs-client    

2、二进制转换库: protobuf.js  bytebuffer.js  long.js

3、纯前端将table导出Excel文件  http://www.jianshu.com/p/74d405940305

    js-xlsx: https://github.com/SheetJS/js-xlsx      用来读取和写文件,

        暴露一个XLSX全局对象
            读取数据XLSX.reder(),读取文件XLSX.readerFile()
            写数据 XLSX.write(),写文件XLSX.writeFile()、写流文件XLSX.stream
            utils对象

    fileSaver: https://github.com/eligrey/FileSaver.js/blob/master/FileSaver.js

4、axios - ajax封装  https://github.com/axios/axios#cancellation

5、iScroll: http://cubiq.org/iscroll-5   http://www.360doc.com/content/14/0724/11/16276861_396699901.shtml

6、Swipper: http://www.swiper.com.cn/

http://www.jq22.com/      jquery插件网

日期

1、momentjs: http://momentjs.cn/            // 日期格式化

####

chalk: https://github.com/chalk/chalk // 可以设置终端log的显示颜色

前端打包工具

1、gulp

2、webpack

3、grunt

调试工具

1、browsersync:   http://www.browsersync.cn/            // 浏览器同步测试工具

    http://www.browsersync.cn/docs/command-line/

产品类

http://www.sketchcn.com/

omniGraffle

管理工具

Confluence 用于团的wiki,和日常工作流程

JIRA   产品版本  产品需求 - 技术开发 - 测试

Stash  git 仓库

/** 工具类 */

查看chrome的DNS缓存对应表: chrome://net-internals#dns

Sublime Text

http://blog.csdn.net/u013861109/article/details/53106074

1、安装package control

        https://packagecontrol.io/

        Control + `(mac) 或 Ctrl+~ (win) 调出console  输入下面命令,查看是否安装成功 Perferences->package settings中看到package control这一项,则安装成功

        import urllib.request,os; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); open(os.path.join(ipp, pf), 'wb').write(urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ','%20')).read())

2、安装编辑器主题

        按下Ctrl+Shift+P,输入install,选择Package Control: Install Package,然后输入Spacegray,选择Theme: Spacegray.

        在菜单栏中选择Preferences->Settings-User,复制以下代码,覆盖打开的文件内容,保存即可应用主题:    
        {
                "theme": "Spacegray.sublime-theme",
            "color_scheme": "Packages/Theme - Spacegray/base16-ocean.dark.tmTheme"
        }

3、设置代码行间距、字号

        需要个性哪个就直接在preferences -> settings user 中的配置添加
        {
            "color_scheme": "Packages/Theme - Spacegray/base16-ocean.dark.tmTheme",
            "theme": "Spacegray.sublime-theme",
            "font_size": "16",
            "line_padding_top": 2,
                "line_padding_bottom": 2
        }


4、安装常用插件

        安装:command + shift + p 输入 ip 回车

        卸载:command + shift + p 输入remove 回车

        1) px转rem插件  https://github.com/flashlizi/cssrem

        1)emmet:html、css快速编写

            如果emmet插件失效:http://www.jianshu.com/p/0862e754cf15

        2)syncedSideBar:侧栏与主界面的颜色相同

        3)babel:ES6、JSX、React

        4)AngularJS

        5)jQuery:jQuery提示

        6)Html5:html5捆

        7)Less:一个Less语法高亮插件

        8)Sass

        9)JsFormat:js 格式化插件

        10)SublimeLinter:行内高亮语法

        11)SideBarEnhancements:一个左边栏增强

        12)SublimeCodeintel:一个代码智能提示引擎

        13)Alignment:Js代码对其插件

        14)BracketHighlighter:代码对其线高亮

        15)Git:git的支持插件

        16)Prefixr:Prefixr Api支持,Prefixr是一个生成css3兼容性的api

        17)LiveReload:网页浏览器页面重新加载插件

        18)Tag:格式化代码排版

                Mac OS X: Command-Option-Shift-F
                Windows: Control-Alt-Shift-F


        19) HTML-CSS-JS Prettify 代码格式化插件 cmd+shift+h

        20)cssrem:sublime的px转rem的插件   https://github.com/flashlizi/cssrem      需要手动下载放到packages中,配置cssrem.sublime文件指定px_to_rem的值 

        21)MarioRicalde-SCSS       SCSS的代码提式和高亮

        react插件   http://www.jianshu.com/p/ecf6c802fdc5?open_source=weibo_search

emmet快捷方法

http://www.w3cplus.com/tools/emmet-cheat-sheet.html

http://www.iteye.com/news/27580

webStorm

1、格式化代码: format   command + option + L

2、install plugins  安装插件

    webstorm/plugins => 插入插件名,然后添加

atom

用于开发react

atom-react-autocomplete 组件名及状态的自动补全 

http://blog.csdn.net/crper/article/details/52196675

vs-Code

安装插件: ext install 插件名

https://marketplace.visualstudio.com/VSCode

1、vue-beautify: vue格式化

2、vue: 语法高亮

3、html-snippets:H5 提示

4、vscode-html-css: 写class可以搜索到所有引用class的值

5、jquerysnippets: jquery提示

6、vscode-JS-CSS-HTML-formatter: html/css/js文件格式化 使用方法: ⌘ + P 输入formatter

7、path-intellisense: 路径自动提示

8、npm-intellisense: 使用require提示

9、vscode-eslint: 语法验证

10、Bootstrap: 

11、vscode-icons: 编辑器菜单中对应文件前加图标   输入icon 选择 File icon Theme

    vscode-icon-theme: 

12、ReactSnippets: ReactJS  jsx文件内 输入 rcc 就可以创建一个react组件的初始代码  
    https://marketplace.visualstudio.com/items?itemName=xabikos.ReactSnippets

13、vscode-node-readme: 可以查看node reuqire中引用的node-module的包内容

14、auto-close-tag: 可以将文档未闭合标签自动加关闭   输入close tag

15、px转rem插件   https://github.com/Maroon1/px2rem 

16、主题类

    Atom One Dark Theme

        vsc-material-theme

        Material Theme

        切换主题  ⌘ + shift + p   =>  输入 them 选择颜色主题在列表中在选择

17、guides: 高亮缩进基准线   ext install guides

18、常见问题

    1) HTML GB2312的乱码问题:code - 首选项 - 设置  在右侧来设置此属性 files.autoGuessEncoding": true

-------------------

1、⌘ + p 搜索插件

2、⌘ + shift + p  命令

3、⌘ + , 打开settings.json配置

4、^(control) + ` 打开vscode自带的终端

5、miniMap的配置  在settings.json中加入 "editor.minimap.enabled": true  配置

6、|http://www.jianshu.com/p/819fc0f7f3b2  配置

7、http://www.cnblogs.com/huaxingtianxia/p/5481493.html   快捷键

8、整行粘贴 sb是⌘+D,   vscode是光标在当前行 ⌘+C, 然后在⌘+V

9、多行光标

    ALT+鼠标

    ALT+上下方向键

    关键词被选中/高亮后,CTRL+D


{
    "workbench.iconTheme": "vscode-icons",
    "workbench.colorTheme": "Atom One Dark",
    "files.autoGuessEncoding": false,
    "window.zoomLevel": -1,
    "editor.fontSize": 13,                    // 文字大小,也可以command +
    "editor.tabSize": 2,                    // tab空格数
    "editor.formatOnType": false,
    "editor.formatOnSave": false,
    "editor.wordWrap": "on"                    // 代码自动换行
}

gitBook

https://segmentfault.com/a/1190000005859901
http://www.chengweiyang.cn/gitbook/introduction/README.html

markdown

https://sspai.com/post/25137

使用工具

1、sFTP - 可视化拖拽上传服务器,也命令行

2、SecureCRT - 纯命令行上传服务器

3、Navicat Premium - Mysql 可视化工具

4、Studio 3T - MongoDB 可视化工具

5、Sourcetree - Git工具

6、VSCode、Sublime、Atom、WebStorm - 前端开发工具

7、

EChart

安装

1、npm install echarts --save

2、引入echarts的两种方式

    页面直接引入文件: <script src="echarts.min.js"></script>

    webpack: import echarts from 'echarts'

3、页面创建DOM的容器

    <div id="main" style="width: 600px;height:400px;"></div>        必须要一个高度值

异步数据加载和更新

1、数据异步

    将数据通过ajax异步取到后,在通过setOption()方式直接加到载插件中


2、loading动画

    showLoading()来显示、hideLoading()隐藏

    Exampole
    var myChart = echarts.init(document.getElementById('main'));

    myChart.showLoading();
    $.ajax({
        success:function(data){
            myChart.hideLoading();
        }
    })


3、数据的动态更新

    只需要加单个数据,先data.push(vlaue), 在通过setOption()将数据渲染出来

    var data = [];        // 存储数据 

    // 创建图表将data数据加入
    ....

    // 添加数据 
    function addData(){
        data.push(Math.random()*100);
    }

    setInterval(function(){
        addData();
        myChart.setOption({
            数据
        })
    },1000)

数据区缩放组件 dataZoom

option = {
    xAxis: {
        type: 'value'
    },
    yAxis: {
        type: 'value'
    },

    dataZoom: [
        {   // 这个dataZoom组件,默认控制x轴。
            type: 'slider', // 这个 dataZoom 组件是 slider 型 dataZoom 组件
            start: 10,      // 左边在 10% 的位置。
            end: 60         // 右边在 60% 的位置。
        }
    ],

    series: [
        {
            type: 'scatter', // 这是个『散点图』
            itemStyle: {
                normal: {
                    opacity: 0.8
                }
            },
            symbolSize: function (val) {
                return val[2] * 40;
            },
            data: [["14.616","7.241","0.896"],["3.958","5.701","0.955"],["2.768","8.971","0.669"],["9.051","9.710","0.171"],["14.046","4.182","0.536"],["12.295","1.429","0.962"],["4.417","8.167","0.113"],["0.492","4.771","0.785"],["7.632","2.605","0.645"],["14.242","5.042","0.368"]]
        }
    ]
}

事件和行为

Echarts中有两种事件,1、用户的鼠标事件   2、交互组件后触发的行为事件

一、鼠标事件

    鼠标事件: 'click'、'dblclick'、'mousedown'、'mousemove'、'mouseup'、'mouseover'、'mouseout'

    myChart.on('click', function(params){
        console.log(params.name)
    })


二、交互组件

    myChart.dispatchAction({ type: '' })        // 通过dispatchAction触发

    1、legendselectchanged: 切换图例开关时触发

    2、datazoom: 数据区域缩放触发


二、params 对象

    {
        // 当前点击的图形元素所属的组件名称,
        // 其值如 'series'、'markLine'、'markPoint'、'timeLine' 等。
        componentType: string,

        // 系列类型。值可能为:'line'、'bar'、'pie' 等。当 componentType 为 'series' 时有意义。
        seriesType: string,

        // 系列在传入的 option.series 中的 index。当 componentType 为 'series' 时有意义。
        seriesIndex: number,

        // 系列名称。当 componentType 为 'series' 时有意义。
        seriesName: string,

        // 数据名,类目名
        name: string,

        // 数据在传入的 data 数组中的 index
        dataIndex: number,

        // 传入的原始数据项
        data: Object,

        // sankey、graph 等图表同时含有 nodeData 和 edgeData 两种 data,
        // dataType 的值会是 'node' 或者 'edge',表示当前点击在 node 还是 edge 上。
        // 其他大部分图表中只有一种 data,dataType 无意义。
        dataType: string,

        // 传入的数据值
        value: number|Array

        // 数据图形的颜色。当 componentType 为 'series' 时有意义。
        color: string
    }

配置选项

1、title: 标题(包括主副标题、链接、样式)

2、legend: 标记的区域 (对legend的显隐、宽高、位置、横纵向排列)

3、grid: 图表的网格区域 (是否显示网格、位标、宽高、背景色、边线色)

4、xAxis、yAxis: x、y坐标轴
    {
        splitLine:{
            show: false,                // 去掉网格线
            lineStyle: {
                color: '#48484a'    // 设置网络线颜色 
            }
        },                
        splitArea : {show : true}                //保留网格区域
    }

5、dataZoom: 数据缩放 ()

6、toolTip: 提示信息,鼠标移到数据点浮现的提示信息()

7、axisPointer:

8、toolBox: 工具栏 (导出图表、数据视图、动态类型切换、缩放、重置)

9、series: 系列列表(来决定图表的类型、图表的数据)

10、color: 图表每一项的颜色

11、background: 图表背景色

12、textStyle: 文本样式

13、animate: 是否开启动画

----- 组件 -------

14、timeline: 时间轴组件

15、graphic: 原生图形元素组件

16、calendar: 日历坐标组件

17、brush: 区域选择组件

18、geo: 地理坐标系组件

19、parallel: 平行坐标系

20、parallelAxis: 这个组件是平行坐标系中的坐标轴

21、singleAxis: 单轴。可以被应用到散点图中展现一维数据

series对象

type: 展示图表的类型

name: 名称

label: 图形上文本标签的控制(show、position、offset、formatter、)

    formatter可以是字符串也可以是函数 

        字符串模板,模板变量有 {a}、{b}、{c},分别表示系列名,数据名,数据值。

        formatter: '{b}: {c}'

        label:{
            normal:{
                formatter: function(data){            // callback
                    return data.percent + '%';
                }
            }
        }, 

        params:
        {
            componentType: 'series',
            // 系列类型
            seriesType: string,
            // 系列在传入的 option.series 中的 index
            seriesIndex: number,
            // 系列名称
            seriesName: string,
            // 数据名,类目名
            name: string,
            // 数据在传入的 data 数组中的 index
            dataIndex: number,
            // 传入的原始数据项
            data: Object,
            // 传入的数据值
            value: number|Array,
            // 数据图形的颜色
            color: string,

            // 百分比
            percent: number,

        }

labelLine: 图形上图形与文本之间连接线的控制

data: 数据

center: 饼图中心坐标

radius: 半径

收集

1、x、y轴文字的颜色和角度

    xAxis: {
        type: 'category',
        boundaryGap: false,
        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
        axisLabel: {            // 这里控制颜色
            show: true,
            textStyle: {
                color: '#fff'
            },
            rotate: 45
        }
    },

参考资料
http://echarts.baidu.com/echarts2/doc/doc.html#Title
http://echarts.baidu.com/gallery/editor.html 在线编辑

EChart

sheetjs 用于读取和导出文件,如Excel、csv

安装

1、CDN src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"

2、$ npm i xlsx --save

3、$ npm install file-saver --save       // 依赖插件,用于对文件的生成保存  https://github.com/eligrey/FileSaver.js

使用

let XLSX = require('xlsx');     // 引用插件
let FileSaver = require('file-saver');

API

一、读写:

    XLSX.readFile('test.xlsx') - 读取文件

    XLSX.read(); 

    XLSX.write(wb, opt);  

    XLSX.writeFile(wb, filename, write_opts); 


二、方法

    XLSX.utils.table_to_book(document.getElementById('tableau'), {sheet:"Sheet JS"});    // 通过table遍历成导出文件

    XLSX.utils.json_to_book()      // 将组装sheet需要的格式,见下面数据格式

    XLSX.utils.sheet_to_json(ws, {header:1, raw:true})


三、输入

    aoa_to_sheet() - 将JS数据数组转换为工作表

    json_to_sheet() - 将一个JSON对象数组转换为工作表

    table_to_sheet() - 将DOM TABLE元素转换为工作表


四、出口: 将Sheet生成的数据转成其它格式:

    XLSX.utils.sheet_to_csv() - 生成CSV

    XLSX.utils.sheet_to_txt() - 生成UTF16格式文本

    XLSX.utils.sheet_to_html() - 生成HTML

    XLSX.utils.sheet_to_json() - 生成一个对象数组

    XLSX.utils.sheet_to_formulae() - 生成公式列表

    Example 将Sheet生成的数据转成html:

        let wb = XLSX.utils.table_to_book(document.getElementById('tab1'), {sheet:"Sheet JS"});
        let sheetData = wb.Sheets['Sheet JS'];
        console.log(XLSX.utils.sheet_to_html(sheetData));


五、通过Blob对象转成文件

    let wb = XLSX.utils.table_to_book(document.getElementById('tab1'), {sheet:"Sheet JS"});
    let fname = '借款.xlsx';
    FileSaver.saveAs(new Blob([s2ab(wb)], {type:"application/octet-stream"}), fname);

    function s2ab(s) {
        if(typeof ArrayBuffer !== 'undefined') {
            let buf = new ArrayBuffer(s.length);
            let view = new Uint8Array(buf);
            for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
            return buf;
        } else {
            let buf = new Array(s.length);
            for (var i=0; i!=s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
            return buf;
        }
    }

格式

let wb = XLSX.utils.table_to_book(document.getElementById('tableau'), {sheet:"Sheet JS"});      // sheet定义的值是返回中数据SheetNames的值

{
    SheetNames:["SheetJSaaa"],      // 这里存的名与Sheets中的名对应
    Sheets:{
        "SheetJSaaa": {
            !merges: [],
            !ref: "A1:F7",              // 指定数据的开始和结束
            A1: {t: 's', v: '创建时间'},        // t:
            A2: {t: "n", v: 43205.613541666666, z: "m/d/yy"},
            B1: {t: "s", v: "业务类型"},
            B2: {t: "s", v: "PAY_DAY_LOAN"}
            .....
        }
    }
}

一、wb - workbook对象

    let wb = XLSX.utils.table_to_book(document.getElementById('tableau'), {sheet:"Sheet JS"});

    1、wb.SheetNames - 工作表的名

    2、wb.Sheets[sheetname] - 返回工作表中存储的数据

    3、wb.Props - 存储标准属性的对象

    4、wb.Workbook - 存储工作簿属性


二、修改单元格的值

    t - 单元格类型:b布尔值,n数字,e错误,s字符串,d日期
    https://docs.sheetjs.com/#cell-object     单元格对象


    let first_sheet_name = wb.SheetNames[0];
    let workSheet = wb.Sheets[first_sheet_name];

    let desired_cell = workSheet['A1'].v;       // 取出v的值


三、设置xlsx单元格行、列样式

    https://docs.sheetjs.com/#formulae

| https://www.gitbook.com/book/sheetjs/docs/details
| https://docs.sheetjs.com/#sheetjs-js-xlsx // 官方文档

LodashJS

LodashJS

工具库,处理数组、对象的一些方法

官网: https://lodash.com/

中文官网: http://lodashjs.com/docs/#_chunkarray-size1

示例

let box = document.querySelector("#box");

let arr = [1,2,3,4,5,6];

// 将数组每两个下标值,转成一个二维数组 
// arr = _.chunk(arr, 2);      // [[1,2], [3,4], [5,6]]

// 删除数组中的false, null, 0, '', undefined, Nan
// arr = [1, 0, 3, '', false, 'ss']
// arr = _.compact(arr);      //   [1,3,'ss'] 

// 合并数组
// arr = [1];
// arr = _.concat(arr, 2, [3], [[4]]);    // [1, 2, 3, [4]]

// 去除数组中指定的数值
// arr = _.difference(arr, [2,3,4]);   // [1,5,6]

// 截取数组从第个开始直到最后的值
// arr = _.drop(arr, 2);      // [3,4,5,6]

// 指定删除的下标个数,从右开始
// arr = _.dropRight(arr, 2);    // [1,2,3]

// 填充数组元素,全部或指定区域
// arr = _.fill(arr, 'a');       // ['a', 'a', 'a', 'a', 'a', 'a'];
// arr = _.fill(arr, '*', 1, 4);    // [1, "*", "*", "*", 5, 6]

// 查找指定的值返回下标
// arr = [
//   {user: 'siguang', age: 30},
//   {user: 'lulu', age: 20},
//   {user: 'haha', age: 10}
// ]
// arr = _.findIndex(arr, function(o){ return o.user == 'lulu' });   // 1
// arr = _.findIndex(arr, ['age', 10])     // 2 如果不存在返回-1

// findLastIndex() 与findIndex()相同只是从后向前
// lastIndex()

// 将一个二维数组转成对象
// arr = [['a', 1], ['b', 2]];
// arr = _.fromPairs(arr);     // {a: 1, b: 2}

// 返回数组第一个、最后一个元素
// arr = _.head(arr);    // 1
// arr = _.last(arr);    // 6

// 根据下标返回值
// arr = _.indexOf(arr, 2);   // 1

// 删除最后一个数组值
// arr = _.initial(arr);     // [1, 2, 3, 4, 5]

// 将数组元素用分割符分开,返回一个字符串
// arr = _.join(arr, '~');      // "1~2~3~4~5~6"

// 根据下标的返回数组中的值,如果是负数从后开始
// arr = _.nth(arr, 2);      // 3
// arr = _.nth(arr, -2);        // 5

// 删除数组中指定的值
// arr = _.pull(arr, 3, 4, 5);   // [1, 2, 6]
// arr = _.pullAll(arr, [3,4,5]);   // [1, 2, 6]

// 返回指定下标的数组值
// arr = _.pullAt(arr, [1,3,5]);   // [2, 4, 6]

// 删除数组元素
arr = _.remove(arr, function(n){ return n % 2 == 0 });    // [2, 4, 6]


console.log(arr);    
box.innerHTML = 'sss'

Nginx

Nginx介绍

服务器分类: Nginx、Apache、tomcat、Micorsoft Server

ng是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器,超越Apache的高性能和稳定性.

 $ sudo /usr/local/Cellar/nginx/1.15.3/bin/nginx                // 本地启动 9080

四层和七层负载均衡

负载均衡设备也被称为"四到七层交换机",四层就是基于IP+端口的负载均衡,七层就是基于URL等应用信息的负载均衡.

如果只做HTTP的负载均衡,用haproxy好了。性能很强

七层负载均衡优点:

    1、高并发连接: 支撑5万并发连接

    2、内存消耗少: 在3万并发连接,开启10个Nginx进程消耗150M内存

    3、配置文件简单

    4、节省带宽: 支持GZIP压缩,可以添加浏览器本地缓存的Header头,

    5、稳定性高: 用于反向代理, 宕机概率小

    6、支持热部署: 不间断服务进行更新

Nginx原理

一、七层负载均衡优势:

    1、对HTTP报头检查,可以检出状态码为400、500、600的错误信息,如果有错误将连接请求重新定向到另一台服务器

    2、可以根据数据类型(判断数据包是图像、压缩文件、或多媒体文件等),将数据引向内容服务器

    3、根据请求类型,将普通文本、图象等静态文档,或是动态文档请求,引向相应的服务器来处理

二、Nginx负载均衡是基于内容和应用的七层资的,Nginx抗并发强,是因为Nginx使用了非阻塞、异步传输

三、模块

    1、nginx负载均衡模块

        配置负载均衡是ngx_http_upstream_module,这模块是默认安装

    2、代理模块

        Proxy为nginx的代理模块, 允许将用户的HTTP请求转发到后端服务器

四、反向代理 

    反向代理是指以代理服务器接受internet上的连接请求,将请求转发给内部服务器,并将从服务器得到结果返回给internet的客户端

Nginx负载均衡调试策略

ng的upstream目前支付几种分配:

1、轮询: 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务down掉,能自动剔除

2、weight: 指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况

    upstream bakend { 
        server 192.168.0.14 weight=10; 
        server 192.168.0.15 weight=10; 
    }

3、ip_hash: 每个请求按访问ip的hash结果分配,每个访客访问一个固定的后端服务器

    upstream bakend { 
        ip_hash; 
            server 192.168.0.14:88; 
            server 192.168.0.15:80; 
        }
    }

4、fair(第三方)

5、url_hash(第三方)

    upstream backend { 
        server squid1:3128; 
        server squid2:3128; 
        hash $request_uri; 
        hash_method crc32; 
    }

通过brew安装nginx

$ brew install nginx

    cd /usr/local/etc/nginx/            // nginx.conf 配置目录

    open /usr/local/Cellar/nginx  // 其实这个才是nginx被安装到的目录

$ cd /usr/local/var/www                // 进入到目录 localhost:9080

$ nginx             // 启动服务

重启ng:

    ps -ef|grep nginx

    kill -9 进程号

Nginx安装和删除

主要步骤: 下载包,压缩、配置编译

$ https://nginx.org/en/download.html    下载一个nginx包版本

$ cd /usr/local/ && mkdir newNginx     // 进入到local目录并创建一个newNginx目录

$ 将下载的包copy到新创建的newNginx目录, 并将包解压到当前目录   tar zxf nginx-1.12.2.tar.gz 

$ cd nginx-1.12.2

$ ./configure        // 验证过程

$ make

$ make install         // 这时候会创建一个nginx目录 /usr/local/nginx

$ 将newNginx目录的文件copy到nginx目录

Nginx配置文件

默认该配置文件被命名nginx.conf

    配置server

    server {
        listen       9092;                                // 端口
        root /Users/apple/siguang.liu/Hh/hh_h5;            // 指定根目录

        location / {
            proxy_pass  http://174.16.1.82:8080/;        // 代理到的服务器
        }

        error_page   500 502 503 504  /50x.html;        // 错误
        location = /50x.html {
            root   html;
        }

        location ^~ /api {
            proxy_pass  http://172.16.1.82:8080/;        // 如果访问以"/api"开头的代理的服务器
        }

        location ~ \.(gif|jpg|png|js|css|html|map)$ {    // 指定静态资源
            root /Users/apple/siguang.liu/Hh/hh_h5;
        }
    }

    可以通过include来将另一个文件的内容引用

    include servers/*.conf;


一、所存在的目录 /usr/local/nginx/conf            // 本机mac /usr/local/openresty/nginx

二、启动  sudo /usr/local/openresty/nginx/sbin/nginx      // 需要sudo管理员权限

三、启动后的可以通过调用带-s参数来执行文件来控制 

    $ nginx -s 命令

    1、reload - 重启  sudo /usr/local/openresty/nginx/sbin/nginx -s reload

    2、stop - 快速关机 sudo /usr/local/openresty/nginx/sbin/nginx -s stop

    3、quit - 优雅关机 sudo /usr/local/openresty/nginx/sbin/nginx -s quit

    4、reopen - 重新打开日志文件 sudo /usr/local/openresty/nginx/sbin/nginx -s reopen

四、查看、杀掉进程

    $ ps -ex | grep nginx

    $ kill -s quit 1682

五、配置文件结构

    指令分为简单指令和块指令,以空格分隔,以分号(;)结束

四、注释使用 #

    # HTTPS server
    #
    # server {
    #    listen       443 ssl;
    #    server_name  localhost;
    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;
    # }

Nginx配置 HTTP2.0

https://www.nginx.com/blog/nginx-1-9-5/

| https://www.cnblogs.com/meng1314-shuai/p/8335140.html // 安装Ng
| http://www.cnblogs.com/felixzh/category/937300.html
| https://www.cnblogs.com/felixzh/p/6283788.html
| https://www.cnblogs.com/taiyonghai/p/6728707.html

大型网站架构

cookie、session、token

一、Session

    是另一种记录客户端状态的机制,cookie保存客户端,session存储在服务器上

    登录成功 => 服务器存储Session => 并在客户端的cookie中也存储一个 => 之后客户端请求,服务端取到cookie的Session的值,在与服务器保存的来进行比较是否存在(这个过程是session内部的机制,程序只需要判断就行)

二、cookie

    存储在客户端本地,js和服务器都可以存、取、删cookie的值,cookie组成(key、value、domain、域、失效时间)

三、token

    token的意思是令牌,用户身份验证,最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串

    作为身份认证 token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击,而session就必须靠链路层来保障通讯安全了。如上所说,如果你需要实现有状态的会话,仍然可以增加session来在服务器端保存一些状态

http://blog.csdn.net/qq_33401924/article/details/52947514
http://blog.csdn.net/jikeehuang/article/details/51488020

验证码的流程

通过插件来生成图型 => 并将图片结果存到session中,并存到用户的cookie中 => 登录时来判断session中的值与用户请求参数的值是否相同

https://github.com/lemonce/svg-captcha/blob/master/README_CN.md

// 生成验证码
async captcha() {
    const svgCaptcha = require('svg-captcha');
    const { ctx } = this;
    const captcha = svgCaptcha.createMathExpr({
        size: 4,                 // 验证码长度
        ignoreChars: '0o1i',     // 验证码字符中排除 0o1i
        noise: 3,                 // 干扰线条的数量
        color: true,             // 验证码的字符是否有颜色,默认没有,如果设定了背景,则默认有
        background: 'rgba(0,0,0,0.3)', // 验证码图片背景颜色
    });
    ctx.session.captcha = captcha.text;
    ctx.type = 'image/svg+xml';        // 设置header的content-type
    ctx.body = captcha.data;
}

// 用户登录
async login() {
    const { ctx, app, service } = this;

    if (ctx.session.captcha && ctx.session.captcha !== ctx.request.body.captcha) {
    this.success({
        data: {},
        message: '验证码错误',
        statusType: app.statusType.otherError,
    });
    return;
    }

    if (
    app.validateParams({
        userName: { type: 'string', max: 100, min: 2 },
        pwd: { type: 'string', min: 1 },
    }, ctx)
    ) {

    const data = await service.auth.login(ctx.request.body);
    this.success(data);
    }
}

http和https

https://segmentfault.com/a/1190000003801450

登录流程

session或token

密码加盐 MD5(username + password + salt)

———————– 概念 ———————–

服务器、虚拟机

服务器: 只是一个硬件虚拟服务只是系统部分

虚拟机: 允许一台HTTP服务器搭建多个web建点,也就是一台服务器可以为多个用户服务,每个用户通过域名运行各自的网站,这就是利用了虚拟机(又称虚拟服务器)的功能

前后分离

前后端数据分离登录失效判断可以通过session服务端来判断 => 跳转会员管理每个页面 => 服务器端判断session是否失效 => 失效跳到登录

其它页面的登录信息可以前端可以通过cookie来获取

正向代理、反向代理 Proxy

一、正向代理: 比如翻墙,直接访问国外网站访问不了,需要可以一个服务器来进行访问。正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径。正向代理还可以使用缓冲特性减少网络使用率。

正向代理

二、反向代理: 代理理服务器来接受网络的连接请求,然后将请求转发给内部网络的服务器 (服务方的需求,为了解决一些负载等问题)

    作用: 保证内网的安全,负载均衡

反向代理
反向代理

http://www.cnblogs.com/Anker/p/6056540.html

CDN和反向代理

CDN: 部署在网络提供的机房,用户请求时可以从最近的网络提供商机房获取数据

负载的均衡

通过反向代理服务器来优化网站的负载

负载的均衡

集群、分布式

跳板机

跳板机是开发者登录到网站分配给应用服务器的唯一途径。开发者必须首先登录跳板机,再通过跳板机登录到应用服务器

k踏板机属于内控堡垒机范围,用于单点登录的主机,之前是为了运维人员远程登录进行管理,会在机房部署跳板机,踏板机就是一台服务器,维护人员在维护过程先要统一登录在这台服务器上在登录到目录服务器进行维护

中间件

缓存

网站缓存有两种:缓存在应用服务器上(本地缓存)和缓存在专门的分布式缓存服务器上(远端缓存)

RESTful架构

CORS跨域资源共享

1、通过设置服务器对header设置一个Access-Control-Allow-Origin: *, 开启跨域请求。在被请求的Response header中加入

    // 指定允许其他域名访问  
    header('Access-Control-Allow-Origin:*');
    // 响应类型  
    header('Access-Control-Allow-Methods:POST');
    // 响应头设置  
    header('Access-Control-Allow-Headers:x-requested-with,content-type');  

2、CORS优点: 跨域最常用的是JSONP但这种方式是通过Get的方式请求src完成的,很多跨域问题JSONP无法解决,比如: 

    1) post请求跨域

    2) "script error" 的脚本错误提示

    3) canvas中无法获取跨域图片的信息,如果使用CORS上面几个问题就可以解决

安全

一、XSS 攻击: 对 Web 页面注入脚本,使用 JavaScript 窃取用户信息,诱导用户操作

二、CSRF 攻击: 伪造用户请求向网站发起恶意请求

三、钓鱼攻击: 利用网站的跳转链接或者图片制造钓鱼陷阱

———————– 网络 ———————–

网关、隧道

网关: 转发其它服务器通信数据的服务器,接收从客户端发送来的

隧道: 将客户端和服务器之间进行中转,并保持双方通信连接的应用程序

TCP/IP

DNS

域名系统(英文:Domain Name System,缩写:DNS)是因特网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网。DNS 使用TCP和UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。

http://www.alloyteam.com/2015/05/dns%EF%BC%8Cnode%E4%BB%A5%E5%8F%8A%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E7%9A%84%E4%B8%80%E4%BA%9B%E7%9F%A5%E8%AF%86%E5%92%8C%E5%BA%94%E7%94%A8/

MongoDB

| 创建用户权限
| 数据类型 - null、boolean、Number、Float、String、Date、表达式、二进制、undefined、Array、Object
| 库操作 - show dbs、show collections、use db、db、db.dropDatabase()
| 创建和删除集合 - db.createCollection、db.myColl.insert({})、db.myColl.drop()
| 删除行 -
| 插入值 - db.myColl.insert({name: ‘haha’})
| 更新值 - db.myColl.update({name: ‘haha}, {$set: {age: 20}}, false, true)
| $set、$unset、$inc、$push、$pushAll、$pop、$pull、$pullAll、$rename
| 删除值 - db.myColl.remove({name: ‘’})、remove({})
| 查询值 - db.myColl.find({})
| .sort()、count()、limite()、skip()
| 查询条件 $gt、$gte、$lt、$lte、!= 、=、and、or、in、notIn
| 数组查询 $all、$size、$sclie
| $where 子句
| 索引 db.myColl.ensureIndex({key:1})、getIndexes()、dropIndexes()、background:true修改索引
| 索引类型: _id索引、单键索引、多键索引、复合索引、过期索引、全文索引、唯一索引
| 复制集
| 分片
| 数据均衡
| 性能分析

什么是MongoDB

MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。

在高负载的情况下,添加更多的节点,可以保证服务器性能。

MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

一、MongoDB优点

    1、无数据结构限制(没有表结构概念,每条记录可以有完全不同的结构)

    2、完全的索引支持(单键索引、数组索引、全文索引、地理位置索引)

    3、数据安全性和分片扩展数据规模

    1、简单的单机服务    2、搭建具有冗余容错功能的复制集    3、搭建大规模数据集群        4、完成集群的自动部署

    MongoDB逻辑结构是一种层次结构,文档(document)、集合(collection)、数据库(database)这三部分组成的。 

二、数据库分类

    1、SQL数据库,支持SQL语言的数据库,如 Oracle,Mysql

    2、NoSQL数据库,不支持SQL语言的数据库,Redis, MongoDB

三、mongo与sql概念

    SQL术语/概念    MongoDB术语/概念    解释/说明

    database         database                 数据库
    table               collection             数据库表/集合
    row                   document                 数据记录行/文档
    column             field                     数据字段/域
    index               index                     索引
    table              joins                      表连接/MongoDB不支持
    primary key     primary key        主键/MongoDB自动将_id字段设置为主键

mongo的基本数据类型

null、boolean、Number、Float、String、Date、表达式、二进制、undefined、Array、Object

启动Mongodb

$ 启动Mongod服务 

    $ cd /usr/local/Cellar/mongodb/4.0.0/bin 

    $ mongod &

    $ 或者sudo ./mongod -f /usr/local/etc/mongod.conf &        // & 为后台运行

$ 停止服务 - 进入 use admin  => $ db.shutdownServer()

查看服务进程 -  ps -rf | grep mongod   ps -rf | grep mongo    kill -9 xxxx

1、命令启动Mongo服务

    // 指定配置文件启动mongod 服务
    mongod --dbpath=/usr/local/var/mongodb       // --logpath=/Users/thatway/mongodata/logs/mongodb.log

2、配置文件方式启动 

    mongod --config /usr/local/etc/mongod.conf

常用命令

$ db.getMongo() - 查看当前mongo的ip和端口

------------------ 库操作 ------------------

db.copyDatabase('旧数据库名', '新数据库名') - 克隆数据库

use myDataBase - 创建并切换库,如果没有就创建这个库,创建库时在内存中,只有对库插入集合操作才会真正存在硬盘上

db - 查看当前选择的库

db.dropDataBase() - 删除数据库,先切到要删除的库下在执行删除命令

db.copyDatabase('ibg_ndoe_sms', 'ibg_node_sms')

show dbs - 查询所有数据库


------------------ 集合 ------------------

show collections 或者 show tables - 查询当前数据库下所有的文档

db.createCollection(表名,指定大小和索引选项) - 创建集合

db.myColl.drop() - 删除当前库下指定集合

db.myColl.insert({_id: ObjectId("5a4b5f29cca1d978501c9c52"), name: 'aa', age: 30}) - 插入指定主键不能相同

db.myColl.save({_id: ObjectId("5a4b5f29cca1d978501c9c52"), name: 'aa', age: 30}) - 插入允许主键相同的数据


db.myColl.find(query) - 取数据

db.myColl.findOne() - 取第一条记录

db.myColl.update({}) - 更新文档

db.myColl.update({name: 'siguang'}, {$unset: {name: 1}}) - 删除一个字段

db.myColl.remove(query, {justOne}) - 删除一条文档


db.myColl.ensureIndex() - 创建索引

db.myColl.getIndexes() - 查看当前集合索引

db.myColl.dropIndexes() - 删除索引 

db.myColl.ensureIndex({id: 1}, {background: true}) - 修改索引


db.createUser() - 创建用户角色

库操作

一、查询库、查询集合

    1、show dbs — 查询所有的数据库列表

    2、show collections — 显示当前库下所有集合


二、创建库和删库

    1、use testDatabase — 创建一个数据库,如果库存在则使用当前库,创建时只在内存中,只有对这个库有操作后这个数据库才能真正创建

    2、db - 查看当前所在的库库

    3、db.dropDatabase() - 删除这个数据库

        use tsetDatabase     // 先进入要操作的数据库
        db.dropDatabase()     // 删除库

文档的创建和删除

查看常用的方法  db.myColl.help()

一、建两种方法

    1、db.createCollection(名称, 指定有关内存大小和索引选项);    -    创建集合

        options:
            capped - Boolean    (可选)如果为true,则启用封顶集合。封顶集合是固定大小的集合,会自动覆盖最早的条目,当它达到其最大大小。如果指定true,则需要也指定尺寸参数。
            autoIndexID - Boolean    (可选)如果为true,自动创建索引_id字段的默认值是false。
            size - number    (可选)指定最大大小字节封顶集合。如果封顶如果是 true,那么你还需要指定这个字段。
            max - number

    2、db.myColl.insert({name:’hf’,age:20}) — 在mongodb中在插入数据时即创建文档,此时创建的是名为myColl的文档

        for(i=0; i<100; i++) db.myTabel.insert({'age', i})        循环插入


二、删除集合、文档

    db.myColl.remove({type: '马尔代夫'}) - 删除myColl集合中 type='马尔代夫' 这条文档

    db.myColl.drop(); — 删除myColl这个集合

insert 插入文档

1、insert() - 插入主键不能相同,自动生成_id    db.myColl.insert({name:’hahaha’, age:12});

2、save() - 允许插入重复数据,直接添加一个文档

    db.myColl.save({        // 直接向集合中插入文档
        data: {},
        message: "操作成功",
        status: 0
    })

二者的区别

    insert()在主键相同时会报错

    save()在主键存在的为更新,如果不存在为插入

    // { "_id" : ObjectId("5a4b5df1cca1d978501c9c50"), "username" : "siguang" }

    $ db.user.insert({ "_id" : ObjectId("5a4b5df1cca1d978501c9c50"), "username" : "siguang" })        // 报错

    $ db.user.save({ "_id" : ObjectId("5a4b5df1cca1d978501c9c50"), "username" : "siguang123" })    // 执行成功,并将username的值改了

remove() 删除文档

1、db.myColl.remove({name: 'hf'}) - 删除name字段值为空的行, 此处相当于关系数据库中的 delete myColl where name = ‘hf’

2、db.myColl.remove({_id: ObjectId("593526143793ca468ceb963c")}) - 通过id来删除文档

3、db.myColl.remove({}) - 删除集合中所有文档

find 文档查询

http://www.cnmyColls.com/egger/p/3135847.html

1、findOne() - 查询第一条记录,然后闭关游标

2、find() - 返回所有记录

    // 返回满足字段值的文档
    db.role.find({age:30}) 

    // 指定返回的列,第一个参数为where语句,第二个参数为不显示列,0为不显示,1为显示
    db.cars.find({}, { user: 0 });

3、sort() - db.myColl.find().sort({age:1})      // age=1为升序,-1为降序  sort()

4、count() - db.myColl.count();          // 返回表中记录的个数 count()        

5、limit() - db.myColl.find().limit(5)          // 返回前5条数据 limit()

        db.myColl.find().skip(10).limit(20);        返回11-30条数据, 用于分页

6、skip() - db.myColl.find().skip(50)          // 跳过前50条数据

7、pretty() - 将查询出的内容进行格式显示        

8、查询条件

    1)条件查询  > $gt、 >= $gte、 < $lt、 <= $lte、 != $ne

        db.cars.find({carMoney: {$lt:100}})        // 查询carMoney小于100的值

        db.cars.find({carMoney: {$lt:100, $gt:20}})        // 查询carMoney 大于20小于100的值

    2)$and、$or、$in、$notIn

        $and  db.cars.find({name: '卡宴', price: 200})        // name=卡宴 并且 price=200    

        $or     db.cars.find({ $or: [ {id: 9}, {carType: 735}] })        // 查询出id=9 或者 carType=735

            // 查询 isDeleted: false 并且id带有'huang'字符 或者 carType等于735
            db.cars.find({ isDeleted: false, $or: [ {id: /huang/i}, {carType: 735}] });    

        $in      db.myColl.find({price: {$in: [100, 300, 500]});        // 查询出price 值为100、300、500值的字段

        $not    不包括的数据

9、$type 类型操作符查询

    例如: 将name字段中的所有为数字的查询出来, db.tourism.find({'name': {$type: 1}})

    对应表:
        类型                        数字            备注

        Double                            1                数字
        String                            2     
        Object                            3     
        Array                                4     
        Binary data                    5     
        Undefined                        6               已废弃。
        Object id                        7     
        Boolean                            8     
        Date                                9     
        Null                                10
        Regular Expression    11
        JavaScript                    13     
        Symbol                            14     
        JavaScript (with scope)    15     
        32-bit integer            16     
        Timestamp                        17     
        64-bit integer            18     
        Min key                            255            Query with -1.
        Max key                            127     


10、数组查询

    1)$all - 用来查询数组中是否包含指定的值

        // 内容列值为数组
        db.myColl.find({content: {$all: [1, 8]})        返回content中包含1或8的数组

    2)$size - 查询数组的长度

        db.myColl.find({content: {$size: 3}});        返回content数组字段长度为3个

    3)$slice - 控制指定字段中返回数组的个数

        db.myColl.find({}, {content: {$slice: 3}} )    返回所有记录 content数组只取前三个

        db.myColl.find({}, {content: {$slice: -3}} )    从后取3个

        db.myColl.find({}, {content: {$slice: [1, 3]}} )    取1-3的范围


11、$where 子句

    相当于用一个js查询一部分,如果为true则返回数据,则否不返回

    字符串形式
    db.myColl.find({$where: "this.title.length > 23"}, {title: 1})    对title field中的字符长度大于23的返回

    函数形式
    db.myColl.find({$where: function(){ return this.title.length > 23 }})


12、Example

    db.myColl.find()  —  查询myColl中的所有数据, 带条件 .fin({x: 1}) x=1的记录

    db.myColl.find({}, {id: 1, price: 1}) — 查询其中两个字段的值

    db.myColl.find({id: 5}, {username: 1}) - 只返回id=5 的 username的字段,其余的不返回

        { "_id" : ObjectId("58e85c84784a18c26f9a1fa5"), "username" : "siguang5" }

    db.myColl.update({}, {$unset:{'name':''}}, false, true)        // 删除一个字段

    db.myColl.find({title: /美舰/}, {title: 1})    -    查找出title中带有"美舰"的字符,并只返回title字段

update 更新文档

update(更新条件, 更新的值,[如果不存在是否创建 - 默认false],[是否更新全部 - 默认false])

1、$set - 更新值

    update() 第四个参数为true更所有匹配的值,false只更新一个

    // 只更匹配的第一条 如果type='123'不存在, 则插入一条只有name='456'的数据
    db.myColl.update({type: '123'}, {name: '456'});        // 注意如果不使用$set那么type=123这行记录只剩name=456

    // 更新全部匹配
    db.myColl.update({name:’hf’}, {$set:{age:25}}, false, true)

    // {multi:true} 更新多条
    db.myColl.update({'title':'MongoDB 教程'}, {$set:{'title':'MongoDB'}}, {multi:true})

    // 为集合中所有文档添加一个字段
    db.user.update({}, {$set: {password: '******'}}, {multi: 1})


2、$unset - 删除字段列

    db.myColl.update({id: 1}, {$unset: {content: 1}});        // 删除id=1,content字段


3、$inc - 只能对一个数字字段的值的进行累加,key不存在或者非数字都报错

    db.myColl.find({id: 1});        // result: { username: 'siguang', password: 100 }

    // 如果password的值存在则 +1000
    db.myColl.update({id: 1}, {$inc: {password: 1000}})    
    db.myColl.find({id: 1});        // result: { username: 'siguang', password: 1100 }


4、$push、$pushAll - 对一个数组字段在插入值

    db.myColl.find({id: 3});            Result: { "id" : 3, "username" : "siguang3",  "content" : [ 1, 2, 3 ] }

    db.myColl.update({id: 3}, {$push: {content: 4}})
    db.myColl.find({id: 3});            Result: { "id" : 3, "username" : "siguang3",  "content" : [ 1, 2, 3, 4] }


5、$addToSet - 向一个数组中添加数据,如果数组中存在这个值则不添加,如果不存在则添到数组中

    db.myColl.find({id: 3});            Result: { "id" : 3, "username" : "siguang3",  "content" : [ 1, 2, 3 ] }

    db.myColl.update({id: 3}, {$addToSet: {content: 3}});        // 数组中存在不添加
    db.myColl.update({id: 3}, {$addToSet: {content: 4}});        // "content" : [ 1, 2, 3, 4 ]


6、$pop - 删除数组中第一个或最后一个值 

    db.myColl.update({id: 3}, {$pop: {content: -1}});        // content为1 删除数组第一个值,-1删除数组最后一个值


7、$pull、$pullAll - 删除数组中指定相同的值

    db.myColl.update({id: 4}, {$set: {content: [1,2,34,4,1,2,3,1,1,6,1,34]}});    将content field为数组

    db.myColl.update({id: 4}, {$pull: {contentn: 1}});
    db.myColl.find({id: 4});        Result  {content: [2,34,4,2,3,6,34]}}  将数组中的1全部删除


8、$rename - 对某个字段进行更名

    db.myColl.update({id: 4}, {$rename: {content: 'title'}});        // 将id=4的 content field 名更改为title


http://chenzhou123520.iteye.com/myColl/1637629

索引

索引就是用来加速查询

索引的优缺点:

    优点: 索引加快查询的速度

    缺点: 增加磁盘空间消耗,降低写入性能

一、命令

    1、查看索引 - getIndexes()    db.myColl.getIndexes()

    2、创建、修改索引 - ensureIndex()    

        创建: db.myColl.ensureIndex({userId: 1})        // 1升序  -1降序

        上修改: db.myColl.ensureIndex({id: 1}, {background: true});        // {background: true}

    3、删除索引 - dropIndexes()

        db.myColl.dropIndexes(name);        // getIndexes()中查出来所索name的值


二、ensureIndex()参数

    1、background - Boolean 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。

    2、unique - Boolean 建立的索引是否唯一。指定为true创建唯一索引。默认值为false.

    3、name - string 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。

    4、dropDups - Boolean 在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.

    5、sparse - Boolean 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.

    6、expireAfterSeconds - nteger    指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。

    7、v - index version 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。

    8、weights - document索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。

    9、default_language - string 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语

    10、language_override - string 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.

http://blog.51cto.com/chenql/2071267


三、索引类型

    创建索引的两种不同:

        非全文索引 ensureIndex({key: value}): key为字段名,值为1或-1代表索引的排序方向
        全文索引     ensureIndex({key: 'text'}): key为字段名,value为固定的'text'字符串

    1、_id索引 - 是绝大多数集合默认建立的索引, 插入一条数据自动创建一个索引

    2、单键索引 - 最普通的索引 与_id不同的是,单键索引不会自动创建

            {x: 1, y: 2, z: 3}        // 当前表

            db.myColl.ensureIndex({x: 1})        // 使用 x 作为索引
            for(var i=0, i<10; i++) db.myColl.insert({x: 2, y: i+'y'; z: i+'z'});
            for(var i=0, i<10; i++) db.myColl.insert({x: 1, y: i+'y'; z: i+'z'});        // 插入10条数据,x为1
            db.myColl.find({x:1});            // 用索引查出数据


    3、多键索引 - 多键索引与单键索引创建形势相同

            单键索引: 值是一个单一的值,如字符串、数字或日期

            多键索引: 值有多个记录,如数组

            db.myColl.insert({x: [1,2,3,4,5]});


    4、复合索引 - 查询条件不只有一个,需要建立复合索引            

        db.myColl.ensureIndex({x: 1, y: 1})        // 定义复合索引
        db.myColl.find({x:1, y: 1})        // 通过复合索引查询

        设置后的索引:
        [
            {
                "v" : 2,
                "key" : {
                    "_id" : 1
                },
                "name" : "_id_",
                "ns" : "tuniu.gt"
            },
            {
                "v" : 2,
                "key" : {
                    "x" : 1,        // 这里
                    "y" : 1
                },
                "name" : "id_1_money_1",
                "ns" : "tuniu.gt"
            }
        ]


    5、过期索引 - 在一段时间后会过期的索引, expireAfterSeconds

        索引过期后数据会被删除, 插入的数据会在30秒后删除, 如用户登录信息, 存储日志

        db.myColl.ensureIndex({time: 1}, {expireAfterSeconds: 30})        // expireAfterSeconds 定义30秒后 time值的索引删除

        db.myColl.insert({username: 'siguang', password: 'xxxx', time: new Date()});        // new Date() 当前时间, 30秒后会自动删除当前这条记录

        ** 注意 当数据量不大的时候最小间隔为60秒, 就算设置30秒也会按60秒来完成 ** 
        ** 创建time的值必须是时间类型ISODate **


    6、全文索引

        *** 注意:mongo中不支持中文的全文索引 ***

        全文索引每次只能使用一个$text查询

        db.myColl.ensureIndex({key: "text"})

        db.myColl.ensureIndex({"$**": "text"})        对所有字段作全文索引,而不是某一个字段


        查询全文索引:

            db.myTabel.find({$test: {$search: 'aa'}})   只有值为aa时不包含其它字符时返回

            db.myTabel.find({$test: {$search: 'aa bb cc'}})   如果是 aa 或 bb 或 cc 时返回  相当于 ||

            db.myTabel.find({$test: {$search: 'aa bb -cc'}})  包含 aa 或 bb ,但不包含 cc 时返回

            db.myTabel.find({$test: {$search: '\'aa\' \'bb\' \'cc\''}})  aa bb cc 都包含  相当于 &&


        相适度: $meta

            {score: {$meta: 'textscore'}}  写在查询条件后面可以返回相似度的结果,与sort一起使用可以达到实用的效果

            Example:

            db.app.find({$text: {$search: '新京报'}}, {score: {$meta: 'textScore'}})

            // db.app.find({$text: {$search: '新京报'}}, {score: {$meta: 'textScore'}}).sort({scope: {$meta: 'textScore'}})       // scope值来排序

            { "_id" : ObjectId("58e31b4c47e9f10d47bd55ec"), "title" : "共享单车相随总理出国门", "article" : "今年1月,摩拜单车创始人", "author" : "新京报(北京)", "dateTime" : ISODate("2017-04-04T04:04:28.585Z"), "score" : 0.75 }
            { "_id" : ObjectId("58e31b4c47e9f10d47bd55ed"), "title" : "李克强赞这家企业一分钟穿越了两个时代", "article" : "当时,来这里考察的。", "author" : "新京报123(北京)", "dateTime" : ISODate("2017-04-04T04:04:28.624Z"), "score" : 0.75 }

            这里结果返回 scope 的值是就相适度的情况


四、索引属性

    1、name 为索引指定name值

        例如定义一个复合索引,可以统一给他们一个名这样,在删除索引的时候也可以通过名字来删除

        db.myColl.ensureIndex({id: 1, type: 1, money: 1}, {name: 'idx'});        // 定义索引name, 如果不加mongo会自动生成一个name值 为key_1

        db.myColl.dropIndexes('idx');


    2、unique 唯一索引

        唯一索引:不能在一个字段插入相同的值,如id如果有1,在插入id=1不允许

        db.myColl.ensureIndex({id: 1}, {unique: true/false});        // 设置了id字段为唯一索引

        db.myColl.insert({id:1, title:'xxx'});        如果id=1存在则不会被插入


    3、sparse 稀疏性


五、地理位置索引

    将一些点的位置存储在mongo中,创建索引后可以按照位置来查找其点

    子分类: 2d索引,用于存储和查找平面上的点        2dsphere索引,用于存储和查找球面上的点

    查找方式: 查找某个点一定距离内的点(打车软件)    查找包含在某个区域内的点

    1、创建 2D索引 平面地理位置索引

        db.location.ensureIndex({w: '2d'})        // 创建索引

        db.location.insert({w: [1, 1]});        // 插入经、纬度, 经度值在-180 至 180 之间, 纬度值在 -90 至 90 之间
        db.location.insert({w: [132, 112]});
        db.location.insert({w: [22, 14]});
        db.location.insert({w: [165, 13]});

        db.location.find({w: {$near: [1,1]}})        // $near 查找近的
        db.location.find({w: {$near: [1,140], $maxDistance: 150}})    // 查找经度 1-150之间, 或者纬度140-150之间   $maxDistrance 最大距离

聚合

aggregate() 主要用于处理数据,返回计算后的数据结果

一、$group: 将集合中的文档分组,用于统计结果

    1、sum - 计算个数    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$sum : "$currentCount"}}}])

    2、avg - 计算平均值    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$avg : "$currentCount"}}}])

    3、min - 获取集合中所有文档对应值得最小值。    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$min : "$currentCount"}}}])

    4、max - 获取集合中所有文档对应值得最大值。    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$max : "$currentCount"}}}])

    5、push - 在结果文档中插入值到一个数组中。    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$push: "$currentCount"}}}])

    6、addToSet - 在结果文档中插入值到一个数组中,但不创建副本。    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$addToSet : "$currentCount"}}}])

    7、first - 根据资源文档的排序获取第一个文档数据。    db.mycol.aggregate([{$group : { _id: "$dimensionType", firstDoc: {$first : "$currentCount"}}}])

    8、last - 根据资源文档的排序获取最后一个文档数据    db.mycol.aggregate([{$group : { _id: "$dimensionType", firstDoc: {$last : "$currentCount"}}}])

    Example:

        // 查出来的文档
        db.col.find().pretty();        
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d0"),
            "dimensionType" : "AGE",
            "loanId" : "113029",
            "currentCount" : 30000,
        },
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d1"),
            "dimensionType" : "OMG",
            "loanId" : "1129602",
            "currentCount" : 30000
        },
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d2"),
            "dimensionType" : "AGE",
            "loanId" : "113031",
            "currentCount" : 40000
        },
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d3"),
            "dimensionType" : "AGE",
            "loanId" : "113016",
            "currentCount" : 40000
        },
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d4"),
            "dimensionType" : "HSR",
            "loanId" : "112910",
            "currentCount" : 30000
        }

        1)通过游标来计算 dimensionType计算出类别的个数

            db.col.aggregate([
                {
                    $group:{
                        _id: "$dimensionType",
                        count: {$sum: 1}
                    }
                }
            ])        

            // 结果 返回
            { 
                "_id" : "HSR", 
                "count" : 1.0
            }
            { 
                "_id" : "OMG", 
                "count" : 1.0
            }
            { 
                "_id" : "AGE", 
                "count" : 3.0
            }

        2) 通过dimensionType列 中不同类型来计算 currentCount列的总合

            db.col.aggregate([
                {
                    $group:{
                        _id: "$dimensionType",
                        total: {$sum: "$currentCount"}
                    }
                }
            ])

            // 返回结果
            { 
                "_id" : "HSR", 
                "total" : 30000.0
            }
            { 
                "_id" : "OMG", 
                "total" : 30000.0
            }
            { 
                "_id" : "AGE", 
                "total" : 110000.0
            }


二、管道符:

    $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。

    $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。

        db.col.aggregate([
            {
                $match: {
                    currentCount: {$gt: 30000}
                }
            },
            {
                $group:{
                    _id: "$dimensionType",
                    min: {$sum: "$currentCount"}
                }
            }
        ])
        先将currentCount字段大于30000的匹配出来,在通过分组取出currentCount的总和

    $limit:用来限制MongoDB聚合管道返回的文档数。

    $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。

    $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。

    $group:将集合中的文档分组,可用于统计结果。

    $sort:将输入文档排序后输出。

    $geoNear:输出接近某一地理位置的有序文档。


三、count()  返回个数

    db.cars.count();        // 返回记录的个数

    db.cars.count({price: 1000})    // 返回price=1000 记录的个数

    db.cars.count({price: {$lt: 1000})    // 返回price < 1000 记录的个数


四、distinct()  指定某一个字段返回不重复的数据,如 age: 'a'  age: 'b'  age: 'a'   

    db.myColl.distinct("price");        // ['a', 'b']    

五、mapReduce()

游标

用户管理

mongo默认是没有管理员账户,需要在admin数据库中使用db.addUser()来添加管理员账号,否则任何人都可以操作数据库,admin库中有system.user的collection这就是用户表,用来存放超级管理员

用户分为两种: 一种是admin用户,另一种是在指定数据库的用户,admin用户是最高权限 

1、createUser() 创建用户

    $ use admin    // 先要切换到admin库

    $ show users     // 显示当前库下设置的所有设置的用户权限

    $ db.createUser(
        {
            user: "root",        // 用户名
            pwd: "ssssss",        // 密码
            roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
        }
    )

    user - 段介绍: user字段,为新用户的名字;
    pwd - 用户的密码;
    cusomData - 为任意内容,例如可以为用户全名介绍;
    roles - 指定用户的角色,可以用一个空数组给新用户设定空角色;可以指定内置角色和用户定义的角色。


    内建的角色

        数据库用户角色:read、readWrite;

        数据库管理角色:dbAdmin、dbOwner、userAdmin;

        集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;

        备份恢复角色:backup、restore;

        所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase

        超级用户角色:root // 这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase)

        内部角色:__system


    Roles(内置角色): 

        Read:允许用户读取指定数据库

        readWrite:允许用户读写指定数据库

        dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile

        userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户

        clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。

        readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限

        readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限

        userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限

        dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。

        root:只在admin数据库中可用。超级账号,超级权限


2、设置完用户权限进行重启mongod服务

    $ db.shtdownServer();        // 关闭mongod服务,或者kill掉

    // 进入bin目录下启动mongod

    $ mongod --auth                // 注意加权限就需要使用这个来启动服务,而不是单独的mongod &


3、mongo登录

    $ mongo --port 27017 -u "root" -p "ssssss" --authenticationDatabase "admin"

    $ use admin

    $ db.auth("root", "ssssss");        // 1表示登录成功,0表示登录失败。


4、创建其它用户

    use myCar
    db.createUser(
        {
            user: "car",
            pwd: "welcomeCar",
            roles: [ 
                { role: "readWrite", db: "myCar" },
                { role: "dbAdmin", db: "myCar" },
                { role: "clusterMonitor", db:"admin"}
            ]
        }
    )


5、作为其它用户进行连接和验证身份

    mongo --port 27017
    use myCar
    db.auth("car", "welcomeCar")


6、修改角色

    db.grantRolesToUser(
        "sms",
        [
            { role: "clusterMonitor", db:"admin"} 
        ]
    )

分片

MongoDB导入、导出及数据库备份与恢复

1、mongoexport - 将 collection 导出成JSON或CSV格式

    mongoexport  -d 库名  -c collection名   -o 输出的文件名   --type 导出的格式json/csv  -f  输出的字段,如果type是CSV需要指定字段名

    Example: sudo mongoexport -d tun -c gt -o gentuanyou --type json


2、mongoimport - 将 collection 导入到

    mongoimport  -d 库名  -c colection名  --file 导入的文件名   --type 导入的格式  -f 导入的字段名  --headerline 如果导入是csv则可以使用第一行标题 


3、mongodump - 库备份

    mongodump  -h 服务器地址   -d 数据库名   -o 备份的位置

    Example: mongodump -h 127.0.0.1 -d tun -o /Users/apple/siguang.liu/mongoBackup


4、mongorestore - 数据库恢复

    mongorestore  -h 服务器地址  -d 需要恢复的数据库   --dir 备份数据的位置    [--drop 恢复先删除数据,然后恢复数据]

    mongorestore -h 127.0.0.1 -d tun --dir /Users/apple/siguang.liu/mongoBackup

监控

对MongoDB服务的运行情况和性能进行监控

1、mongostat、mongoStop      mongostat是mongdb自带的状态检测工具, 查看mongo运行状态的程序

    使用: 先到bin目录 cd /usr/local/Cellar/mongodb/3.4.3/bin                进行 mongostat目录 $ mongostat --help   来查看文档

            mongostat -h 127.0.0.1:123    -u用户名 -p密码        执行侦听

    日志: 

        http://www.cnmyColls.com/zhuque/archive/2013/03/29/2988577.html

        insert    插入数量
        query    查询数量
        update  更新数量
        delete     删除数量
        getmore 
        command 
        flushes    虚拟映射
        mapped     
        vsize   占磁盘的空间
        res     占内存大小
        idx miss 如果值过高,说明索引创建的有问题
        qrw     qr 读队列,qw 写队列 性能指标的一块,如果值比较高出现性能问题
        arw 
        net_in 
        net_out 
        conn    连接mongo的数量            
        time

2、profile 集合介绍

    db.getProfilingStatus();        // 获取

3、日志介绍

4、explain(): 

    db.users.find({id: 10000}).explain('executionStats')

    explain()三个参数:'queryPlanner', 'executionStats', 和'allPlansExecution'

    result:
    {
        "queryPlanner" : {
            "plannerVersion" : 1,
            "namespace" : "myCar.users",
            "indexFilterSet" : false,
            "parsedQuery" : {
                "name" : {
                    "$eq" : "user99989"
                }
            },
            "winningPlan" : {
                "stage" : "COLLSCAN",
                "filter" : {
                    "name" : {
                        "$eq" : "user99989"
                    }
                },
                "direction" : "forward"
            },
            "rejectedPlans" : [ ]
        },
        "executionStats" : {
            "executionSuccess" : true,        // 是否成功
            "nReturned" : 1,                // 返回的数量
            "executionTimeMillis" : 49,        // *** 重要的执行时间   
            "totalKeysExamined" : 0,
            "totalDocsExamined" : 100000,    // 总共检查了多少个文档
            "executionStages" : {
                "stage" : "COLLSCAN",
                "filter" : {
                    "name" : {
                        "$eq" : "user99989"
                    }
                },
                "nReturned" : 1,
                "executionTimeMillisEstimate" : 50,
                "works" : 100002,
                "advanced" : 1,
                "needTime" : 100000,
                "needYield" : 0,
                "saveState" : 783,
                "restoreState" : 783,
                "isEOF" : 1,
                "invalidates" : 0,
                "direction" : "forward",
                "docsExamined" : 100000
            }
        },
        "serverInfo" : {
            "host" : "appledeMacBook-Pro-2.local",
            "port" : 27017,
            "version" : "3.4.3",
            "gitVersion" : "f07437fb5a6cca07c10bafa78365456eb1d6d5e1"
        },
        "ok" : 1
    }

MongoDB安装、连接、启动服务

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"    // 安装brew

$ brew update                // 更新brew

$ brew install mongodb         // 安装的目录 /usr/local/Cellar/mongodb/   

    brew uninstall mongodb  // 卸载mongo

$ brew list                    // 查看brew安装的列表中是否存在brew

$ sudo mkdir -p /data/db       // 用来存放mongo创建的数据文件

    注意这里如果启动服务时报/data权限问题需要执行

    $ sudo chmod -R 777 /data

$ 连接本地和远端服务器的mongoDB

    本地mongo: $ mongo             // 无密码

                        // 用户名admin、密码123456,登录本地端口为27017的test数据库
                        $ mongo mongodb://admin:123456@localhost:27017/test                    

    远端mongo: $ mongo 192.168.1.200:27017/test -u user -p password        // test为数据库名

        mongodb://10.10.13.123:27017,10.10.13.341:27017/ibg_node_core

$ 启动和关闭服务

    启动服务: 

        $ cd /usr/local/Cellar/mongodb/4.0.0/bin        // 进入到目录
        $ mongod &            // & 关闭终端mongod服务不会被kill掉  如果启用权限使用 mongod --auth

    关闭服务:

        $ use admin         // 需要先进入到admin库
        $ db.shutdownServer()

$ mongo --version            // 查看版本

https://www.imooc.com/article/23046

.conf配置文件

$ brew info mongodb    // 查看安装conf文件位置: mongod --config /usr/local/etc/mongod.conf

mongodb.conf:

    systemLog:                                // log目录                    
        destination: file
    path: /usr/local/var/log/mongodb/mongo.log
        logAppend: true
    storage:                                    // db目录
        dbPath: /usr/local/var/mongodb        // 数据存储的目录
    net:
        bindIp: 128.0.0.1
    security:
        authorization:enabled   // 开启权限

http://blog.csdn.net/sun491922556/article/details/74973191            // 3.4版本配置

收集

1、使用mongoShell语句来通过_id查询更新时需要加ObjectId(""), 如果程序处理不需要加

    db.col.update({_id: ObjectId("59acc404bef510c028190630")},{$set: {'by': 'mongodb'}})

填坑

1、首次安装 创建存放数据的目录时 

    $ sudo mkdir -p /data/db  如果这两个文件夹的权限是root那启动mongod就会报错,需要修改一下这两个目录的权限

    $ sudo chown apple:admin /data        // apple为我当前用户的名称

    $ sudo chown apple:admin /data/db

2、启动时如果提示 Failed to unlink socket file /tmp/mongodb-27017.sock errno:1 Operation not permitted

    因为/tmp/mongodb-27017.sock这个文件没有操作权限, 是root用户启动没成功后创建了这个文件
    需要到tmp目录下删除这个文件在重启

    $ cd /tmp && sodu rm -rf mongodb-27017.sock

3、Navicat Premium导出和导入集合

    导出:集合 -> 右键(导出向导)—> 选择导出文件类型json  
            注意:导出的json文件会在josn中自动创建一个RECORDSkey来存放数据,用于导出时的指定映射

    导入:集合 -> 右键(导入向导)—> 按步骤
            注意 第3步的时候 (表示一个集合行的标签 , 选择 "RECORDS"(Parent(Root))) ),勾选下面将标签属性视为集合字段
                    第7步,选择复制:删除目录全部记录,并从源重新导入

| http://www.mongoing.com // 中文网站
| http://www.jianshu.com/p/dd0c39bf7be4 // mongo安装
| http://www.runoob.com/mongodb/mongodb-objectid.html // 文档
| http://www.yiibai.com/mongodb/mongodb_drop_database.html
| http://blog.csdn.net/jaylong35/article/details/7219410 // 服务的开启与关闭
| http://blog.csdn.net/dbabruce/article/details/50963956 // 用户权限
| http://www.cnblogs.com/qingtianyu2015/p/5968400.html // 库的导入、导出
| https://robomongo.org // mongoDB可视化工具
|
| http://blog.csdn.net/u013457382/article/category/6114612
| http://www.cnblogs.com/zhongweiv/p/node_mongodb.html

Mongoose

概念

Schema - 数据库存储格式的约定协议,可以理解为数据表的字段类型声明

Model -  由Schema转化的数据模型,具有抽象属性和行为的数据库操作,可以进行查询操作

Entity - 由Model创建的实体,可以对数据库表进行完整的CRUD操作

Mongoose使用

一、安装

    $ npm install mongoose

二、示例

    const mongoose = require('mongoose');
    const Schema = mongoose.Schema;

    // 连接mongodb
    mongoose.connect('mongodb://car:welcomeCar@localhost/myCar');       // mongodb://用户名:密码@数据库IP/库名

    // 连接成功
    mongoose.connection('connected', ()=>{
        console.log('connect success');
    })

    // 连接失败
    mongoose.connection('error', ()=>{
        console.log('connect error' + err);
    })

    // 连接断开
    mongoose.connection('disconnected', ()=>{
        console.log('connect disconnected');
    })

    // 创建Schema
    const UserSchema = new Schema({
        username: String,
        password: String,
        age: Number,
        LoginAt: Date
    })

    // 定义Model
    const UserModel = mongoose.model('User', UserSchema);

    // 插入数据
    let userData = new UserModel({
        username: 'siguang',
        password: 'ssssss',
        age: 20,
        loginAt: new Date()
    })

    // 保存
    userData.save((err, res)=>{
        if(err){
            return console.log(err)
        }
        console.log(res);
    })

    // 删除
    userData.remove({age: 30}, (err, doc) => {
        if(err){
            return console.log(err)
        }
        console.log(doc);
    })

    // 查询
    userData.find({username: 'siguang', (err, doc)=>{
        if(err){
            return console.log(err)
        }
        console.log(doc);
    })

    // 数量
    userData.count({age: 20}, (err, doc)=>{
        if(err){
            return console.log(err)
        }
        console.log(doc);
    })

连接

mongoose两种连接: connect连单个db并打开,createConnect连接多个db

一、mongoose.connect()方法连接

    写法1:
        connect('mongodb://[username]:[password]@host:port/database?options...');   // 用户名、密码、主机、端口、库名、参数
        let db = mongoose.connect('mongodb://[username]:[password]@127.0.0.1:27017/myDB');

    写法2:
        -- conect(uri, options) --
        var options = {
                db: { native_parser: true },
                server: { poolSize: 5 },
                replset: { rs_name: 'myReplicaSetName' },
                user: 'myUserName',
                pass: 'myPassword'
        }
        var uri = 'mongodb://localhost/dbName?poolSize=4';
        mongoose.connect(uri, options);
        -- mongoose.createConnection() --

二、多个连接

    let mongoose = require('mongoose');
    let db = mongoose.connect('mongodb://127.0.0.1:27017/myDB');        // mongodb://IP:端口号/数据库名

    // 侦听打开的回调
    db.connection.on('error', function(error){
        console.log('数据库连接失败'+error);
    })

    // 侦听连接成功
    db.connection.on('open', function(){
        console.log('连接成功')
    })

三、两者的区别

    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 mongoose = require('mongoose');
    mongoose.connect('mongodb://localhost/test');
    db = mongoose.connection;
    db.once('open', function callback () {
            // yay!
    });    

    createConnection,可以open,但完全不会查询。第二种方法就可以

Schema

Schema: 一种文件形式存储数据库模型的骨架,无法直接连接数据端,不具备操作数据库的能力,叫数据属性模型或集合

一、定义表的文档结构

    let personSchema = new mongoose.Schema({        
        name: String,
        age: Number,
        email: { type: String, max: 20 }
    })

二、实例方法、静态方法

    let PersonSchema = new mongoose.Schema({        
        name: String,
        age: Number,
        email: { type: String, max: 20 }
    })

    var Person = mongoose.model('person', PersonSchema);
    var silence = new Person({ name: 'Silence' });

    PersonSchema.methods.speak = function(){ }

三、index 索引

    let Schema = mongoose.Schema;
    let carSchema = new Schema({
        name: String,
        title: { type: String, index: true },   // index 索引
        uid: { type: Number, unique: true },    // unique 独一无二的
        date: { type: Date, default: Date.now } // default 默认值
    })

    // 文档索引和字段索引
    let carSchema = new Schema({
        name: String,
        title: { type: [String], index: true },   // 字段索引
    })

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

Schema Type

https://xiaoxiami.gitbook.io/mongoose/guide/schemas/typesmd

一、类型

    1、String:字符串

    2、Number:数值

    3、Date:日期

    4、Buffer: 二进制

    5、Boolean:布尔

    6、Mixed: 混合

    7、ObjectId: ObjectId

    8、Array:数组

二、其它参数

    default: 默认       // updated: { type: Date, default: Date.now }

    min/max: 最小或最大  // age: { type: Number, min: 18, max: 65 }

    trim: 去掉两端空格

    lowercase: true     // 保存前将字符转成小写

    uppercase: true     // 保存前将字符转成大写

    required: true      // 必填

    match:RegExp       // 创建一个正则验证器

    enum:Array         // 检查值是否在给定的数组中

    index: true         // 索引

    unique: true        // 索引,指定字段为独一无二

三、Example

    var schema = new Schema({
        idCard: { type: String, unique: true, trim: true },     // 用户id 字段独一无二、去掉两端空格
        name:    String,            // 可以直接写成String,也可以写成 {type: String}
        binary:  Buffer,
        living:  Boolean,
        updated: { type: Date, default: Date.now }
        age:     { type: Number, min: 18, max: 65 }
        mixed:   Schema.Types.Mixed,
        _someId: Schema.Types.ObjectId,
        array:      [],
        ofString:   [String],
        ofNumber:   [Number],
        ofDates:    [Date],
        ofBuffer:   [Buffer],
        ofBoolean:  [Boolean],
        ofMixed:    [Schema.Types.Mixed],
        ofObjectId: [Schema.Types.ObjectId],
        nested: {
            stuff: { type: String, lowercase: true, trim: true }
        }
    })

Model

具有操作数据库的能力,类似管理数据库的属性和行的类

创建model  mongoose.model('集合名', schema);

    let personScheam = new Scheam({
        name: 'String',
        password: 'String'
    }, {
        timestamps: true,             // 设置timestamps,多加两个字段createdTime、updatedTime,来记录插入时间和更新时间
        collection: 'report_warning_config',
    })

    let personModel = mongoose.model('person', personSchema);

查询

一、find, findById, findOne, or where 

    let TankScheam = new Scheam({
        name: 'String',
        password: 'String'
    })

    let Tank = mongoose.model('Tank', personSchema);

    Tank.find({size: 'samll'}).where('createDate').gt(oneYear).exec(callback);

二、条件查询中常用属性

    $or    或关系
    $nor    或关系取反
    $gt    大于
    $gte    大于等于
    $lt    小于
    $lte    小于等于
    $ne    不等于
    $in    在多个值范围内
    $nin    不在多个值范围内
    $all    匹配数组中多个值
    $regex    正则,用于模糊查询
    $size    匹配数组大小
    $maxDistance    范围查询,距离(基于LBS)
    $mod    取模运算
    $near    邻域查询,查询附近的位置(基于LBS)
    $exists    字段是否存在
    $elemMatch    匹配内数组内的元素
    $within    范围查询(基于LBS)
    $box    范围查询,矩形范围(基于LBS)
    $center    范围醒询,圆形范围(基于LBS)
    $centerSphere    范围查询,球形范围(基于LBS)
    $slice    查询字段集合中的元素(比如从第几个之后,第N到第M个元素


三、方法

    1、where('price') - 查询的字段  Tank.find().where('price')

    2、find() - 查询所有,返回的是数组

    3、findOne({name: 'siguang'}) - 只把第一条name为siguang的数据,如果find会将所有都返回

    4、findById(id) - 根据一条id来查找,返回的是一条记录的对象,而不是一个数组,与find({_id: '59bf7ee03f55167fb6cdd75c'})相同

    5、findByIdAndRemove(id) - 根据id查找,并删除这个条数据,如果查找不到返回 null

    6、findByIdAndUpdate(id, update) - 

    7、lean() - Tank.find().lean()      // 默认参数为true, 可以设置 lean(false)

删除

Tank.remove({size: 'large'})

// 查找并删除
Tank.findByAndRemove()

更新

Tank.update({_id: id}, {$set: {size: 'large'}, callback);

// 查找并更新
Tank.findByIdAndUpdate(id, [update]);

Entity

save()

insert和update都需要save(),

egg-mongose 总结

1、问题描述:连接mongoose的过程中遇到mongodb collection自动加s,比如mongo库中有一个userTest集合,如果使用inser会新创建一个userTests

    解决:在创建mode的时候要指定集合名

    module.exports = app => {
        const mongoose = app.mongoose;

        const UserTestSchema = new mongoose.Schema({
            idx: { type: Number },
            password: { type: String }
        });
        return mongoose.model('userTest', UserTestSchema, 'userTest');            // 这里第三个参数要加
    }

1、Model中创建模型

    module.exports = app => {
        const mongoose = app.mongoose;

        const NewsSchema = new mongoose.Schema({
            newsId: { type: Number },
            newsTitle: {type: String, max: 32},
            newsContent: {type: String},
        },{
            timestamps: true,               // 插入记录时会自动创建一个createAt和updateAt时间字段
            collection: 'news',             // mongo中存的collection名
        });

        NewsSchema.index({ 'newsId': 1 });    // newsId为索引

        return mongoose.model('News', NewsSchema);      // News调用时的名
    }

2、在service中调用

    let doc = await app.model.News.find();

3、创建和查询

    const doc = await new app.model.User(user).save();          // 创建时需要new
    const user = await app.model.User.findOne({_id: user._id});     // 查询时不需要new

4、使用find()查询

    如果使用find().lean()返回的是纯javascript对象,而不是mongoose文档,他们没有保存方法

    const resourceTree = await app.model.Resource.find({});

    const resourceTree = await app.model.Resource.find({}).lean();

    返回
    [
        { _id: 5a535142fe6d170e82135e89,
            displayName: '欢欢',
            username: 'huanhuan',
            mobile: 13012309874,
            email: 'huan@126.com' 
        },
        { _id: 5a5357d2bd53b40f791362aa,
            username: 'maolv',
            displayName: '毛驴',
            mobile: 13290984585,
            email: 'maolv@126.com' 
        }
    ]

5、查询条件写法lt

    const password = app.model.UserTest.find().where('idx').lt(5);        // 返回idx字段中小于5的条数

6、更新

    async addChannel(params) {
  const channel = await app.model.ConfigBusinessChannel.findOne({ businessType: params.businessType });
  if (channel) {
    return app.renderBody({
      statusType: app.statusType.recordAlreadyExisted,
    });
  }

  const channelModel = new app.model.ConfigBusinessChannel({
    businessType: params.businessType, // 业务渠道ID
    businessName: params.businessName, // 业务渠道名
    isEnabled: params.isEnabled, // 是否启用
    paySignedCompanys: [], // 签约的结算主体
  });
  await channelModel.save();

  const response = app.renderBody({
    statusType: app.statusType.success,
    data: {},
  });

  return response;
}

| https://mongoose.shujuwajue.com/guide/schemas.html // 中文API
| http://www.nodeclass.com/api/mongoose.html
| https://github.com/eggjs/egg-mongoose egg-mongoose
| http://cnodejs.org/topic/504b4924e2b84515770103dd
| http://www.cnblogs.com/xuange306/p/4603551.html
| http://www.cnblogs.com/winyh/p/6682039.html
| http://cnodejs.org/topic/504b4924e2b84515770103dd
| http://www.hubwiz.com/class/543b2e7788dba02718b5a4bd

nodeJS(之一)Stream

| createReadStream() - 创建可读流
| createWriteStream() - 创建可写流
| setEncodeing() - 设置编码
|

Stream

Stream把较大的数据,拆分成小的部分

读取文件的两种: fs.readFile()和fs.createReadStream()

stream提供了以下四种类型的流:

    var Stream = require('stream');

    var Readable = Stream.Readable;
    var Writable = Stream.Writable;
    var Duplex = Stream.Duplex;
    var Transform = Stream.Transform;

createReadStream()、createWriteStream()

// 创建一个Readable对象以读取bigFile内容
// 如果使用fs.readFile()可以会由于文件过大而失败
fs.createReadStream(bigFile);

setEncodeing() 设置编码

var readerStream = fs.createReadStream('input.txt');

readerStream.setEncodeing('UTF8');

事件

可读数据流的事件

    readable 数据向外流时触发

    data 对于那些没有显式暂停的数据流,添加data事件监听函数,会将数据流切换到流动态,尽快向外提供数据

    end 读取完数据时触发。注意不能和 writeableStream.end() 混淆,writeableStream 并没有 end 事件,只有 .end() 方法

    close 数据源关闭时触发

    error 读取数据发生错误时触发


可写数据流的事件

    drain writable.write(chunk) 返回 false 之后,缓存全部写入完成,可以重新写入时就会触发

    finish 调用 .end 方法时,所有缓存的数据释放后触发,类似于可读数据流中的 end 事件,表示写入过程结束

    pipe 作为 pipe 目标时触发

    unpipe 作为 unpipe 目标时触发

    error 写入数据发生错误时触发

| https://cnodejs.org/topic/570b1fa494b38dcb3c09a7f8
| http://fe.meituan.com/stream-basics.html