nosql之间的比较
memcached key-value缓存
redis key-value存储数据库
mongoDB 文档数据库,存储的是文档(Bson->json的二进制文件)
特点:内部执行引擎js解释器,把文档存储为bson结构,查询时,转换为JS对象,并可以通过熟悉的js语法来操作。
mongo和传统型数据库相比最大的不同
传统型数据库:结构化数据,定好了表结构后,每一行的内容,必须是符合表结构的,列的个数和类型都一样。
mongo文档型数据库:表下面的每篇文档都可以有自己独特的结构。
{
mid:3,
author: xxx,
conment: [
{
cid:97,
content:'好电影!'
},
{
cid:98,
content:'确实好!',
reply: [
{
rid: 3,
content: '你说的对'
}
]
}
]
}
安装
- 下载mongodb www.mongodb.org 下载最新stable版
- 解压文件
-
不用编译,本身就是编译后的二进制可执行文件
- 启动mongodb服务
/path/bin/mongod --dbpath /path/to/database --logpath /path/to/log-file --fork --port 27017
参数解释:
- --dbpath 数据存储目录
- --logpath 日志存储文件
- --port 运行端口(默认27017)
- --fork 后台进程运行
- mongodb非常占磁盘空间,刚启动要3-4G空间,如果用虚拟机练习,可能空间不够用,导致无法启动,可以用
--smallfiles
选项来启动,将会占用较小空间,400M左右。
- 连接mongo
/path/bin/mongo
1. mongo入门命令
1.1 查看当前数据库
show dbs;
1.2 选库
use databaseName;
1.3 查看当前库下的表(在MySQL中叫tables,在mongo中叫collections)
show tables/collections;
1.4 mongo中use一个不存在的库时,会自动创建这个库(称为:隐式创建)
use dbname
1.5 显式创建一个表(如果你不创建,直接向其中加入一个文档,该Collection也会被隐式创建出来)
use dbname; //先选库
db.createCollection('name'); // 通过db对象的方法创建库
1.6 删除一个表(Collection)
use dbname; // 先选库
db.collectionName.drop(); // 通过db中collection对象的方法删除库
1.7 删除数据库
use dbname; //先选库
db.dropDatabase(); // 通过db对象的方法删除库
2. 基本操作-增删改查
- 增
语法: db.collectionName.insert(document);
use dbname;
// 增加单个文档
db.collectionName.insert({title:'nice day'});
// 增加多个文档
db.collectionName.insert([
{"title":"nice day"},
{"name":"lili", "age":16}
]);
// 查看, 若没_id这个字段,mongo会自动增加这个字段
db.collectionName.find();
- 删
语法: db.collectionName.remove(查询表达式,选项);
use dbname;
// 这条会报错
db.collectionName.remove();
// 全部删除
db.collectionName.remove({});
// 删除name为lili的数据
db.collectionName.remove({"name":"lili"});
// 删除age为19的数据,所有age=19的数据都会被删除
db.collectionName.remove({"age":19});
// 只删一条age为19的数据
db.collectionName.remove({"age":19}, true);
- 改
语法: db.collectionName.update(查询表达式,新值,选项);
选项 {upset:true/false, multi:true/false}
upsert 是指没有匹配的行,则直接插入该行
multi 是指修改多行(即使查询表达式命中多行,默认也只改1行,如果想修改多行,可以用此选项)
use dbname;
// 将name=lilei的数据age改为32,这里会将这条数据变为只有_id和age的数据!
db.collectionName.update({"name":"lilei"}, {"age":32});
// 修改单个字段的正确方式$set
db.collectionName.update({"name":"lilei"}, {$set:{"age":32}});
// 修改单个字段并添加选项
db.collectionName.update({"name":"lilei"}, {$set:{"age":32}}, {upsert: true});
- 查
语法:
db.collectionName.find(查询表达式,选项);
db.collectionName.findOne(查询表达式,选项);
use dbname;
// 查询所有,展示所有列
db.collectionName.find();
// 带表达式和选项,选项表示要查age列(_id始终都有)
db.collectionName.find({"name": "hmm"}, {"age": 1});
// 查询一行
db.collectionName.findOne({"age": 1});
3. 查询表达式
- 最简单的查询表达式 { field : value}
查询field为value的文档。 - $ne 不等与
语法: { field : {$ne : value}}
use dbname;
// 查询age≠19的数据
db.collectionName.find({"age": {$ne:19}});
- $in 在某数组中
语法: { field : {$in : [value1, value2, ....]}}
use dbname;
// 查询goods表中cat_id为2或8的文档
db.goods.find({"cat_id" : {$in : [2, 8]}});
- $nin 不在某数组中 not in
语法: { field : {$nin : [value1, value2, ....]}}
use dbname;
// 查询goods表中cat_id不为2或8的文档
db.goods.find({"cat_id" : {$nin : [2, 8]}});
- $all field的值为数组,且至少包含所给值
语法: { field : {$all : [value1, value2, ....]}} - $exists 查询含有某字段的文档
语法: { field : {$exists : 1}}
use dbname;
// 查找含有age字段的文档
db.collection.find({"age" : {$exists:1}});
- $nor 返回所有条件都不满足的文档
语法: { $nor : [条件1, 条件2]} - 正则表达式查询
use dbname;
// 查询产品名以诺基亚开头的文档
db.collectionName.find({"goods_name" : /诺基亚.*/}, {"goods_name" : 1});
- $where 表达式查询
注意:用$where查询时,mongodb是把bson结构转为json对象,然后比较对象的属性是否满足表达式,所以速度交慢。
use dbname;
// 查找cat_id≠3且cat_id≠11的文档
db.collection.find({$where : "this.cat_id != 3 && this.cat_id != 11"});
4. 游标操作
游标是什么?
通俗的说,游标不是查询结果,而是查询的返回资源或者接口,通过这个接口,你可以逐条读取。就像php中fopen打开文件,得到一个资源句柄一样,通过这个句柄,可以一行一行的读文件。
use dbname;
// 声明游标
var cursor = db.collectionName.find(query, projection);
// 判断游标是否已经取到尽头
cursor.hasNext();
// 取出游标的下一个单元,是bson结构,人无法识别
cursor.next();
// 用while来循环游标
var mycursor = db.bar.find({"_id" : {$gt: 5}});
while(mycursor.hasNext()) {
// 通过printjson打印这个bson文档
printjson(mycursor.next());
}
// foreach 也可以
mycursor.foreach(function (obj) {
printjson(obj);
})
5. group分组(求平均,求和等)
方法: aggregate
db.goods.aggregate([
// 匹配哪些行
{$match: {}},
// 针对哪个字段分组,别名:$field
// 根据哪个字段求值 , 别名 : { $求值方法 : "$field"}
{$group: {"bieMin": "$cat_id", "total" : {$sum: "$price"}}},
]);
6. Map-Reduce(分布式的group)
相比aggregate聚合操作,Map-Reduce支持分布式的数据(大数据,在不同的地点、服务器上)。
先 map: 分类。
后 reduce: 统计。
use dbname;
// map 函数
var map = function () {
// 将cat_id相同的文档的goods_number放一起
// this指的是遍历的每条数据
emit(this.cat_id, this.goods_number);
};
// reduce 函数
var reduce = function (cat_id, numbers) {
// 分类好后,根据cat_id字段中的numbers来求和
return Array.sum(numbers);
};
// 进行mapReduce操作,第三个参数表示将输出结果放到res这个表中
db.goods.mapReduce(map, reduce, {out:"res"});
// 查看结果
db.res.find();