node干货

 

 

 

Node是什么?

 

Node.js,或者 Node,是一个可以让JavaScript运行在服务器端的平台。它可以让

JavaScript 脱离浏览器的束缚运行在一般的服务器环境下,就像运行 Python、Perl、PHP、Ruby程序一样。你可以用 Node.js 轻松地进行服务器端应用开发,Python、Perl、PHP、Ruby能做的事情 Node.js 几乎都能做,而且可以做得更好。

 

为了给大家一个直观的认识:

下面给大家演示一个例子:

启动F:\nodeExample下的app.js文件

浏览器访问:http://127.0.0.1:3000/

这样就有个感性的认识。

 

Node基于GoogleV8引擎封装的,来自 Google Chrome 项目。V8 号称是目前世界上最快的 JavaScript 引擎,并提供了一些编写服务器程序的常用接口,例如文件流的处理。Node的目的是提供一种简单的途径来编写高性能的网络程序。

 

Node的起源:

Node最初是由Ryan Dahl开发的开源项目,被joyent公司收购

Node.js 是一个让 JavaScript运行在服务端的开发平台,它让 JavaScript成为脚本语言世界的一等公民。

Node.js 可以作为服务器向用户提供服务,与 PHP、Python、Rubyon Rails 相比,它跳过了 Apache、Nginx等 HTTP服务器,直接面向前端开发

 

Node特点:

Node.js 是一个为实时WebReal-time Web)应用开发而诞生的平台,它从诞生之初就充分考虑了在实时响应、超大规模数据要求下架构的可扩展性。这使得它摒弃了传统平台依靠多线程来实现高并发的设计思路,而采用了单线程、异步式I/O、事件驱动式的程序设计模型。这些特性不仅带来了巨大的性能提升,还减少了多线程程序设计的复杂性,进而提高了开发效率

下面详细阐述下有关这方面的内容,让大家了解的更多:

        

传统平台:多线程实现高并发,开发复杂

Node平台最大的特点:

1.单线程

2.异步式I/O 【非阻塞I/O<--通过回调来实现 ,

3.事件驱动

 

 

通过学习node还会对 JavaScript 有一个全新的认识,

因为服务端的 JavaScript中没有 DOM 和BOM,也不存在浏览器之间的兼容性问题。

当然这里的兼容指的是操作对象上的兼容(比如获得某个对象里面的文本,有的是用object.html()而有的用的是object.text,这里只是举个例子,),样式css上的兼容还是依然存在的(尽管他用了ejs模板或者jad模板)之前还用过volicity的模板技术

 

为什么要用这样的架构:后面举例说明:

对于高并发的解决方案

1.传统的架构:是多线程模型,也就是为每个业务逻辑提供一个系统线程,通过系统线程切换来弥补同步式 I/O 调用时的时间开销。

2.Node.js 使用的是单线程模型,对于所有 I/O 都采用异步式的请求方式,避免了频繁的上下文切换。Node.js在执行的过程中会维护一个事件队列,程序在执行时进入事件循

环等待下一个事件到来,每个异步式I/O 【非阻塞I/O请求完成后会被推送到事件队列,等待程序进程进行处理。

例如,对于简单而常见的数据库查询操作,按照传统方式实现的代码如下:

res = db.query('SELECT * from some_table');

res.output();

传统架构解决办法:

以上代码在执行到第一行的时候,线程会阻塞,等待数据库返回查询结果,然后再继续

处理。然而,由于数据库查询可能涉及磁盘读写和网络通信其延时可能相当大(长达几个

到几百毫秒,相比CPU的时钟差了好几个数量级),线程会在这里阻塞等待结果返回。

对于高并发的访问,cup要付出的代价:

一方面线程长期阻塞等待,

二、另一方面为了应付新请求而不断增加线程,因此会浪费大量系统资源,

三、同时线程的增多也会占用大量的 CPU 时间来处理内存上下文切换,

四、而且还容易遭受低速连接攻击。

Node架构解决办法:

看看Node.js是如何解决这个问题的:

db.query('SELECT * from some_table', function(res) {

res.output();

});

这段代码中 db.query 的第二个参数是一个函数,我们称为回调函数。进程在执行到db.query 的时候,不会等待结果返回,而是直接继续执行后面的语句,直到进入事件循环。

当数据库查询结果返回时,会将事件发送到事件队列,等到线程进入事件循环以后,才会调

用之前的回调函数继续执行后面的逻辑。

Node.js 的异步机制是基于事件的,所有的磁盘I/O、网络通信、数据库查询都以非阻塞

的方式请求,返回的结果由事件循环来处理。图1-1 描述了这个机制。Node.js 进程在同一时刻只会处理一个事件,完成后立即进入事件循环检查并处理后面的事件。这样做的好处是,

一、.CPU和内存在同一时间集中处理一件事,同时尽可能让耗时的 I/O 操作并行执行。

二、.对于低速连接攻击,Node.js只是在事件队列中增加请求,等待操作系统的回应,因而不会有任何多线程开销,很大程度上可以提高 Web 应用的健壮性,防止恶意攻击

 

Node.js 中,异步式I/O 是通过回调函数来实现的

下面举例说明:

实例:运行F:\sources\chap3\sec2中的node    readfile.js

var fs = require('fs');

fs.readFile('file.txt', 'utf-8',function(err, data) {

  if(err) {

   console.error(err);

  }else {

   console.log(data);

  }

});

console.log('end.');

fs.readFile 调用时所做的工作只是将异步式 I/O 请求发送给了操作系统,然后立即

返回并执行后面的语句执行完以后进入事件循环监听事件.fs 接收到I/O 请求完成的事件时,事件循环会主动调用回调函数以完成后续工作

 

Node运行结果测试:

下面看看测试结果:

Snoopyxd 详细对比了 Node.js与 PHP+Nginx 组合,结果显示在3000并发连接、30秒的测试下,输出“helloworld”请求:

PHP 每秒响应请求数为3624,平均每个请求响应时间为0.39秒;

Node.js 每秒响应请求数为7677,平均每个请求响应时间为0.13秒。

而同样的测试,对MySQL查询操作:

PHP 每秒响应请求数为1293,平均每个请求响应时间为0.82秒;

Node.js 每秒响应请求数为2999,平均每个请求响应时间为0.33秒。

关于 Node.js的性能优化及生产部署,我们会在第6章详细讨论。

 

 

有关Npm

 

 

Node.js 有着强大而灵活的包管理器(node package manager,npm),

目前已经有上万个第三方模块,其中有

a.网站开发框架,Express

b.有 MySQL、PostgreSQL、MongoDB数据库接口,

c.有模板语言解析、CSS 生成工具、邮件、加密、图形、调试支持,

d.甚至还有图形用户界面和操作系统 API工具。

 

Node支持情况:

由 VMware公司建立的云计算平台 CloudFoundry 率先支持了 Node.js。2011年6月,微软宣布与 Joyent 公司合作,将 Node.js 移植到 Windows

Node.js 能做什么

正如 JavaScript为客户端而生,Node.js 为网络而生。Node.js 能做的远不止开发一个网站那么简单,使用 Node.js,你可以轻松地开发:

具有复杂逻辑的网站;

基于社交网络的大规模 Web 应用;

Web Socket 服务器;//比如聊天服务器  高并发,业务逻辑简单,就是分发信息 ;

TCP/UDP 套接字应用程序;

命令行工具;

交互式终端程序;

带有图形用户界面的本地应用程序;

单元测试工具;

客户端 JavaScript 编译器。

Node.js 内建了 HTTP服务器支持,也就是说你可以轻而易举地实现一个网站和服务器

的组合。这和 PHP、Perl不一样,因为在使用 PHP 的时候,必须先搭建一个 Apache 之类的。HTTP服务器,然后通过 HTTP服务器的模块加载或 CGI 调用,才能将 PHP 脚本的执行结果呈现给用户。而当你使用 Node.js 时,不用额外搭建一个HTTP 服务器,

为什么?给大家解释下原因:

因为 Node.js本身就内建了一个。这个服务器不仅可以用来调试代码,而且它本身就可以部署到产品环境,它的性能足以满足要求。

Node.js 还可以部署到非网络应用的环境下,比如一个命令行工具。Node.js 还可以调用C/C++的代码,这样可以充分利用已有的诸多函数库,也可以将对性能要求非常高的部分用C/C++ 来实现。

 

其实nodejs就开一个进程,用事件驱动,那就是个转发器,连接器,其他业务逻辑和数据存储那是本地机器的问题

 

题外话:

CommonJS规范

包括了:

模块(modules)、

包(packages)、

系统(system)、

二进制(binary)、

控制台(console)、

编码(encodings)、

文件系统(filesystems)、

套接字(sockets)、

单元测试(unit testing)等部分。目前大部分标准都在拟定和讨论之中,已经发布的标准有Modules/1.0、Modules/1.1、Modules/1.1.1、Packages/1.0、System/1.0。

移植到浏览器外的计划不止一个,但Node.js 是最出色的一个。随着 Node.js 的成功,各种浏览器外的 JavaScript 实现逐步兴起,因此产生了 CommonJS 规范

Commonjs作用

CommonJS 试图拟定一套完整的 JavaScript规范,以弥补普通应用程序所需的 API,譬如文件系统访问、命令行、模块管理、函数库集成等功能。CommonJS制定者希望众多服务端 JavaScript实现遵循CommonJS 规范,以便相互兼容和代码复用。Node.js 的部份实现遵循了CommonJS规范,但由于两者还都处于诞生之初的快速变化期,也会有不一致的地方

 

 

而当你使用 Node.js时,不用额外搭建一个 HTTP服务器,因为 Node.js 本身

就内建了一个。这个服务器不仅可以用来调试代码,而且它本身就可以部署到产品环境,它

的性能足以满足要求。

 

有关事件

Node.js 所有的异步 I/O 操作在完成时发送一个事件到事件队列。在开发者看来,事

件由 EventEmitter 对象提供。前面提到的 fs.readFile 和 http.createServer 的回调函数都是通过 EventEmitter 来实现的。

下面我们用一个简单的例子说明 EventEmitter的用法:

//event.js

var EventEmitter= require('events').EventEmitter;

var event= new EventEmitter();

event.on('some_event',function() {//注册事件

console.log('some_event occured.');

});

setTimeout(function() {

event.emit('some_event');//也就是该事件发送到事件队列,等待执行

}, 1000);

运行这段代码,1秒后控制台输出了 some_event occured.。其原理是 event 对象

注册了事件 some_event 的一个监听器,然后我们通过 setTimeout 在1000毫秒以后向

event 对象发送事件 some_event,此时会调用 some_event 的监听器。

 

Node.js 的事件循环机制

Node.js 在什么时候会进入事件循环呢?答案是 Node.js 程序由事件循环开始,到事件循

环结束,所有的逻辑都是事件的回调函数,所以 Node.js 始终在事件循环中,

程序入口就是事件循环第一个事件的回调函数。事件的回调函数在执行的过程中,可能会发出 I/O 请求或直接发射(emit)事件,执行完毕后再返回事件循环,事件循环会检查事件队列中有没有未处理的事件,直到程序结束

 

 

与其他语言不同的是,Node.js 没有显式的事件循环,类似 Ruby 的 EventMachine::run()的函数在 Node.js 中是不存在的。Node.js的事件循环对开发者不可见,由 libev 库实现。libev支持多种类型的事件,如 ev_io、ev_timer、ev_signal、ev_idle 等,在 Node.js中均被EventEmitter 封装。libev 事件循环的每一次迭代,在 Node.js中就是一次 Tick,libev 不断检查是否有活动的、可供检测的事件监听器,直到检测不到时才退出事件循环,进程结束。

API简单介绍

说在api前面:

全局对象:

浏览器端javascript:(传统js) 全局对象:window

 

服务器段javascript(node)      全局对象:global   是所有全局变量的属主:

 

 

全局变量定义:

在最外层定义的变量;

全局对象的属性;

隐式定义的变量(未定义直接赋值的变量)。

比如在在js文件中,直接写一个变量 x=1;则这个x就是全局变量,所以:

永远使用var 定义变量--以避免引入全局变量,因为全局变量会污染

命名空间,提高代码的耦合风险

 

 

一些常用对象:

 

Node.js 提供了 exports require 两个对象,

exports 是模块公开的接口,

require 用于从外部获取一个模块的接口,即所获取模块的 exports 对

require 不会重复加载模块,也就是说无论调用多少次 require,获得的模块都是同一个

//loadmodule.js

var hello1= require('./module');

hello1.setName('BYVoid');

var hello2= require('./module');

hello2.setName('BYVoid 2');

hello1.sayHello();

 

运行后发现输出结果是 Hello BYVoid 2,这是因为变量 hello1 和 hello2 指向的是

同一个实例,因此 hello1.setName 的结果被 hello2.setName 覆盖,最终输出结果是

由后者决定的

 

 

process.nextTick() 提供了一个这样的工具,可以把复杂的工作拆散,变成一个个较小的事件。

function doSomething(args, callback) {

somethingComplicated(args);//耗时

callback();

}

doSomething(function onEnd() {

compute();//耗时

});

Node.js 核心模块

我们假设 compute() 和 somethingComplicated() 是两个较为耗时的函数,以上

的程序在调用 doSomething() 时会先执行 somethingComplicated(),然后立即调用

回调函数,在 onEnd() 中又会执行 compute()。下面用 process.nextTick() 改写上

面的程序:

 

 

function doSomething(args, callback) {

somethingComplicated(args);

process.nextTick(callback);

}

doSomething(function onEnd() {

compute();

});

改写后的程序会把上面耗时的操作拆分为两个事件,减少每个事件的执行时间,提高事

件响应速度。

 

Javascript的面向对象特许是基于原型的。与常见的基于类的不同

没有提供对象继承的语言级特许,而是通过原型复制来实现

util.inherits(constructor,superConstructor)是一个实现对象间原型继承

的函数,注意这里【只是原型继承】

var util= require('util');

function Base(){

this.name= 'base';

this.base= 1991;

this.sayHello= function() {

console.log('Hello ' + this.name);

};

}

Base.prototype.showName = function() {

console.log(this.name);

 

};

function Sub(){

this.name= 'sub';

}

util.inherits(Sub, Base);

var objBase= new Base();

objBase.showName();

objBase.sayHello();

console.log(objBase);

var objSub= new Sub();

objSub.showName();

//objSub.sayHello();

console.log(objSub);

我们定义了一个基础对象 Base 和一个继承自 Base 的 Sub,Base 有三个在构造函数

内定义的属性和一个原型中定义的函数,通过 util.inherits 实现继承。运行结果如下:

base

Hello base

{ name: 'base', base: 1991, sayHello: [Function]}

sub

{ name: 'sub' }

注意,Sub 仅仅继承了 Base 在原型中定义的函数,而构造函数内部创造的 base 属

性和 sayHello 函数都没有被 Sub 继承。同时,在原型中定义的属性不会被 console.log 作

为对象的属性输出。如果我们去掉objSub.sayHello(); 这行的注释,将会看到:

node.js:201

throw e; // process.nextTick error, or 'error'event on first tick

^

TypeError: Object #<Sub> has no method 'sayHello'

at Object.<anonymous>(/home/byvoid/utilinherits.js:29:8)

at Module._compile (module.js:441:26)

at Object..js (module.js:459:10)

at Module.load (module.js:348:31)

at Function._load (module.js:308:12)

at Array.0 (module.js:479:10)

at

 

util.inspect

util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换为字符串的方法,通常用于调试和错误输出。它至少接受一个参数 object,即要转换的对象

util.isArray()、

util.isRegExp()、

util.isDate()、

util.isError() 四个类型测试工具,以及

util.format()、

util. debug() 等工具。

有兴趣的读者可以访问 http://nodejs.org/api/util.html了解详细内容。

 

 

事件驱动 events

 

events 模块只提供了一个对象象: events.EventEmitter。

EventEmitter的核心就是事件发射事件监听器功能的封装

 

。EventEmitter 的每个事件由一个事件名和若干个参

数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter支持

若干个事件监听器。当事件发射时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。让我们以下面的例子解释这个过程:

var events= require('events');

var emitter= new events.EventEmitter();

emitter.on('someEvent',function(arg1, arg2) {

console.log('listener1', arg1, arg2);

});

emitter.on('someEvent', function(arg1, arg2) {

console.log('listener2', arg1, arg2);

});

emitter.emit('someEvent','byvoid', 1991);

运行的结果是:

listener1 byvoid 1991

listener2 byvoid 1991

以上例子中,emitter 为事件 someEvent 注册了两个事件监听器,然后发射了

someEvent 事件。运行结果中可以看到两个事件监听器回调函数被先后调用。

 

这就是EventEmitter最简单的用法。接下来我们介绍一下EventEmitter常用的API。

EventEmitter.on(event,listener) 为指定事件注册一个监听器,接受一个字

符串 event 和一个回调函数 listener。

EventEmitter.emit(event,[arg1], [arg2], [...]) 发射 event 事件,传

递若干可选参数到事件监听器的参数表。

EventEmitter.once(event,listener) 为指定事件注册一个单次监听器,即

监听器最多只会触发一次,触发后立刻解除该监听器。

EventEmitter.removeListener(event,listener) 移除指定事件的某个监听

器,listener 必须是该事件已经注册过的监听器。

EventEmitter.removeAllListeners([event])移除所有事件的所有监听器,

如果指定 event,则移除指定事件的所有监听器。

更详细的 API 文档参见 http://nodejs.org/api/events.html。

文件系统fs

var fs = require('fs');

fs.readFile('content.txt', 'utf-8', function(err, data) {

if (err) {

console.error(err);

} else {

console.log(data);

}

});

Node.js异步编程接口习惯:

以函数的最后一个参数为回调函数,通常一个函数只有一个回调函数,回调函数的参数中第一个是err,其余的参数是其他返回的内容,如果没有发生错误,err的值会是null或者undefined.如果有错误发生,err通常是Error对象的实例

 

异步编程设计的缺陷:

这种异步事件模式的弊端也是显而易见的,因为它不符合开发者的常规线性思路,往往

需要把一个完整的逻辑拆分为一个个事件,增加了开发和调试难度。针对这个问题,Node.js

第三方模块提出了很多解决方案,

 

 

 

 

 

 

 

有关调试:

方式一、eclipse

方式二、浏览器:【只能在 Chrome、Safari等 WebKit 内核的浏览器中使用,而不支持 Firefox 或 Internet Explorer】

原因:node-inspector 使用了 WebKit Web Inspector,因此只能在 Chrome、Safari等 WebKit 内核的浏览器中使用,而不支持 Firefox 或 Internet Explorer。

方式一:下面是具体截图:

eclipse调试的时候:需要主动点击nodeDebug才能开始调试

步骤:1.debug模式启动node文件:

2.点击eclipse中的nodeDebug

 

点击完后,开始调试,会出现一个新的文本文件,并且该文件只读,此时就可以给该只读文件加断点调试了:

 

二、浏览器调试:

需要先安装一个node-inspector

命令:npm install  -g   node-inspector  全局安装,因为要直接在任意命令行用,而不是针对某个应用:

安装好好需要做三件事:

1.启动要调试的js文件 : node --debug-brk=5858 xxx.js

2.启动node-inspector命令

3.打开浏览器访问:http://127.0.0.1:8080/debug?port=5858

这样就可以在浏览器中进行断点调试了

 

 

 

Mongo非法关闭启动失败解决方法:

 

1、删除%MONGO_HOME%/db下的.lock文件

 

2、输入命令mongod --repair

 

3、重启mongoDB

 

 

最后给大家演示一个用nodejs开发的例子:

启动mongo数据库:

cd 到mongo的bin目录下:

mongod --dbpath "c:\ProgramFiles\mongodb\data"

 

1、正常启动

mongod --dbpath /usr/mongo/data --logfile/var/mongo.log

说明:

指定数据存储目录和日志目录,如果采用安全认证模式,需要加上--auth选项,如:

mongod --auth --dbpath /usr/mongo/data--logfile /var/mongo.log 

2、以修复模式启动

mongod --repair

以修复模式启动数据库。

实际很可能数据库数据损坏或数据状态不一致,导致无法正常启动MongoDB服务器,根据启动信息可以看到需要进行修复。或者执行:

mongod -f /etc/mongodb.conf --repair

3、终止服务器进程

db.shutdownServer()

 

启动node工程:

cd F:\sources\chap5\sec7\microblog

node app.js

 

下面给大家演示下node的写法:

在演示之前,为了让大家能看懂接口,先补充下mongo的知识:

 

补充完后给大家写一下,让大家感性的体会下node的写法:

 

 

最后总结一句:Everything is Ajax

mogo补充,

 

 

Nodejs的api地址:

http://chat.nodejs.org/

 

一些应该用开发的:

http://www.csdn.net/article/2013-12-17/2817827-10-surprising-Node.js-projects

 

有关nodejs的一些应用场景,写的挺好的一篇文章:

http://www.oschina.net/question/91955_47352

 

http://www.csdn.net/article/tag/node.js

 

补充:

MongoDb基本命令

1、showdbs

显示当前数据库服务器上的数据库

2、use pagedb

 切换到指定数据库pagedb的上下文,可以在此上下文中管理pagedb数据库以及其中的集合等

3、show collections(原先的showtables,查看所有表)

显示数据库中所有的集合(collection)

4、db.serverStatus()  

查看数据库服务器的状态。示例如下所示:

5、查询指定数据库统计信息

usefragment

db.stats()

6、查询指定数据库包含的集合名称列表

db.getCollectionNames()//获取所有的表名称

["posts","sessions", "system.indexes","users" ]

二)基本DDL和DML

 

1、创建数据库

如果你习惯了关系型数据库,你可能会寻找相关的创建数据库的命令。在MongoDB中,你可以直接通过use dbname来切换到这个数据库上下文下面,系统会自动延迟创建该数据库

> show dbs  

admin   0.03125GB  

local   (empty)  

pagedb  0.03125GB  

test    0.03125GB  

> use LuceneIndexDB  

switched to db LuceneIndexDB  

> show dbs  

admin   0.03125GB  

local   (empty)  

pagedb  0.03125GB  

test    0.03125GB  

> db  

LuceneIndexDB  

> db.lixlTable.save({'userName':'lixl','company':'test'});

建表的第一种方式:db.表名.save('字段1''1','字段2':'2');//直接写入新的表名,并用save插入值

> show dbs  

lixlTable 0.03125GB  

admin   0.03125GB  

local   (empty)  

pagedb  0.03125GB  

test    0.03125GB  

>  

可见,在use指定数据库后,并且向指定其中的一个集合并插入数据后,数据库和集合都被创建了。



2、删除数据库

直接使用db.dropDatabase()即可删除数据库。直接删除当前use的db

>show dbs;
lixl    0.0625GB
local   0.03125GB
microblog       0.0625GB
> db.dropDatabase();
{ "dropped" : "lixl", "ok" : 1 }

3、创建集合//其实就是创建表

可以使用命令db.createCollection(name,{ size : ...,capped : ..., max : ... } )创建集合,示例如下所示:

[plain] viewplaincopy

1.  >  db.createCollection('lixlTable2',{'userName':'linan'});

 建表的第二种方式:

db.createCollection('表名'{'capped':true, 'size':10240, 'max':17855200})

//只是建立表没有插入值

后面的这三个参数名称是固定的,但是可以没有:

         capped:

         size:大小

         max:最大值

可以直接写db.createCollection('表名')

2. { "ok" : 1 }  

3. > show collections  

4. lixlTable2

5. storeCollection  

6. system.indexes  

4、删除集合

删除集合,可以执行db.mycoll.drop()。

5、插入更新记录

直接使用集合的save方法,如下所示:

 

db.lixlTable2.save({ "type" : "google",  "os" :"chrom",  "address" : "california"})

更新记录,使用save会将原来的记录值进行覆盖实现记录更新。

6、查询一条记录[类型select * fromtableName  where xxx = xxxx]

 

使用findOne()函数,参数为查询条件,可选,系统会随机查询获取到满足条件的一条记录(如果存在查询结果数量大于等于1)示例如下所示:

 db.lixlTable2.findOne({'address':'california'});

{
       "_id" :ObjectId("52b1beefda6a86cb17c990c6"),
       "type" : "google",
       "os" : "chrom",
       "address" : "california"

}

7、查询多条记录[类型select * from tableName]

使用find()函数,参数指定查询条件,不指定条件则查询全部记录。

>db.lixlTable2.find({'address':'california'});
{ "_id" : ObjectId("52b1beefda6a86cb17c990c6"),"type" : "google", "os" : "chrom
", "address" : "california" }
{ "_id" : ObjectId("52b1bf0bda6a86cb17c990c7"),"type" : "google", "os" : "chrom
", "address" : "california" }
>

8、删除记录

使用集合的remove()方法,参数指定为查询条件,示例如下所示:

a.根据条件删除:

 

db.lixlTable2.remove({'name':'lixl'})

b.全部删除:

db.lixlTable2.remove()

9、创建索引

可以使用集合的ensureIndex(keypattern[,options])方法,示例如下所示:

>use pagedb

switchedto dbpagedb

>db.page.ensureIndex({'title':1,'url':-1})

>db.system.indexes.find()

{"name": "_id_", "ns" : "pagedb.page","key" :{ "_id" : 1 }, "v" : 0 }

{"name": "_id_", "ns" :"pagedb.system.users","key" : { "_id" : 1 },"v" : 0}

{"_id": ObjectId("4ef977633c1fc4613425accd"), "ns":"pagedb.page", "key" : {"title" :1,"url" : -1 }, "name" :"title_1_url_-1","v" : 0 }

10、查询索引

我们为集合建立的索引,那么可以通过集合的getIndexes()方法实现查询,示例如下所示:

[plain] viewplaincopy

1.  > db.page.getIndexes()  

2. [  

3.         {  

4.                 "name" : "_id_", t3223

5.                 "ns" : "pagedb.page",  

6.                 "key" : {  

7.                         "_id" : 1  

8.                 },  

9.                 "v" : 0  

10.         },  

11.         {  

12.                 "_id" : ObjectId("4ef977633c1fc4613425accd"),  

13.                 "ns" : "pagedb.page",  

14.                 "key" : {  

15.                         "title" : 1,  

16.                         "url" : -1  

17.                 },  

18.                 "name" : "title_1_url_-1",  

19.                 "v" : 0  

20.         }  

21. ]  

当然,如果需要查询系统中全部的索引,可以使用db.system.indexes.find()函数。
11、删除索引

删除索引给出了两个方法:

[plain] viewplaincopy

1.  db.mycoll.dropIndex(name)  

2. db.mycoll.dropIndexes()  

第一个通过指定索引名称,第二个删除指定集合的全部索引。

13、统计集合记录数

usefragment

db.baseSe.count()
统计结果,如下所示:

[plain] viewplaincopy

1.  > use fragment  

2. switched to db fragment  

3. > db.baseSe.count()  

4. 36749  

上述统计了数据库fragment的baseSe集合中记录数。



=========================================================

mongoDB特点:

如果插入这样三个对象则,

{
  "_id" : ObjectId("52b1bbd792ba3c19705afe4b"),
  "name" : "lixl",
  "address" : "bj"
}


/* 1 */
{
  "_id" : ObjectId("52b1bc6d92ba3c19705afe4c"),
  "type" : "apple",
  "os" : "ios",
  "company" : "apple"
}


/* 2 */
{
  "_id" : ObjectId("52b1bceb92ba3c19705afe4d"),
  "type" : "windows",
  "os" : "windows",
  "address" : "seattle"
}

数据库是这样的:

 

也就是说,如果插入的json数据,有不同的列则,这些列会取并集。

 

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值