关于MongoDB的学习

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: '你说的对'
                }
            ]
        }
    ]
}

安装

  1. 下载mongodb www.mongodb.org 下载最新stable版
  2. 解压文件
  3. 不用编译,本身就是编译后的二进制可执行文件

    《关于MongoDB的学习》 mongo可执行文件介绍

  4. 启动mongodb服务
/path/bin/mongod --dbpath /path/to/database --logpath /path/to/log-file --fork --port 27017

参数解释:

  • –dbpath 数据存储目录
  • –logpath 日志存储文件
  • –port 运行端口(默认27017)
  • –fork 后台进程运行
  1. mongodb非常占磁盘空间,刚启动要3-4G空间,如果用虚拟机练习,可能空间不够用,导致无法启动,可以用
--smallfiles 

选项来启动,将会占用较小空间,400M左右。

  1. 连接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. 查询表达式

  1. 最简单的查询表达式 { field : value}
    查询field为value的文档。
  2. $ne 不等与
    语法: { field : {$ne : value}}
use dbname;
// 查询age≠19的数据
db.collectionName.find({"age": {$ne:19}});
  1. $in 在某数组中
    语法: { field : {$in : [value1, value2, ….]}}
use dbname;
// 查询goods表中cat_id为2或8的文档
db.goods.find({"cat_id" : {$in : [2, 8]}});
  1. $nin 不在某数组中 not in
    语法: { field : {$nin : [value1, value2, ….]}}
use dbname;
// 查询goods表中cat_id不为2或8的文档
db.goods.find({"cat_id" : {$nin : [2, 8]}});
  1. $all field的值为数组,且至少包含所给值
    语法: { field : {$all : [value1, value2, ….]}}
  2. $exists 查询含有某字段的文档
    语法: { field : {$exists : 1}}
use dbname;
// 查找含有age字段的文档
db.collection.find({"age" : {$exists:1}});
  1. $nor 返回所有条件都不满足的文档
    语法: { $nor : [条件1, 条件2]}
  2. 正则表达式查询
use dbname;
// 查询产品名以诺基亚开头的文档
db.collectionName.find({"goods_name" : /诺基亚.*/}, {"goods_name" : 1});
  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"}}}, 
]);

《关于MongoDB的学习》 mongoDB分组示意图

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();
    原文作者:PYM_祺
    原文地址: https://www.jianshu.com/p/020ec8feef49
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞