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是基于Google的V8引擎封装的,来自 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 是一个为实时Web(Real-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),
目前已经有上万个第三方模块,其中有
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" ]
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 : ... } )创建集合,示例如下所示:
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()方法实现查询,示例如下所示:
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、删除索引
删除索引给出了两个方法:
1. db.mycoll.dropIndex(name)
2. db.mycoll.dropIndexes()
第一个通过指定索引名称,第二个删除指定集合的全部索引。
13、统计集合记录数
usefragment
db.baseSe.count()
统计结果,如下所示:
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数据,有不同的列则,这些列会取并集。