mongodb-MongoDB记录

mongodb-MongoDB记录


前篇


适用场景

总结起来,如果你的业务满足一个或多个特点,那么选择MongoDB是个正确的决定:

    • 无需要跨文档或跨表的事务及复杂的join查询支持 // 目前已经支持事务,join的支持也越来越好。
      • 敏捷迭代的业务,需求变动频繁,数据模型无法确定
      • 存储的数据格式灵活,不固定,或属于半结构化数据
      • 业务并发访问量大,需数千的QPS
      • TB级以上的海量数据存储,且数据量不断增加
      • 要求存储的数据持久化、不丢失
      • 需要99.999%的数据高可用性
      • 需要大量的地理位置查询、文本查询

比如游戏、物流、电商、内容管理、社交、物联网、视频直播等,以下是几个实际的应用案例。

  • 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
  • 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
  • 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
  • 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
  • 视频直播,使用 MongoDB 存储用户信息、礼物信息等

如果你还在为是否应该使用 MongoDB,不如来做几个选择题来辅助决策(注:以下内容改编自 MongoDB 公司 TJ 同学的某次公开技术分享)。

应用特征Yes / No应用不需要事务及复杂 join 支持必须 Yes新应用,需求会变,数据模型无法确定,想快速迭代开发?应用需要2000-3000以上的读写QPS(更高也可以)?应用需要TB甚至 PB 级别数据存储?应用发展迅速,需要能快速水平扩展?应用要求存储的数据不丢失?应用需要99.999%高可用?应用需要大量的地理位置查询、文本查询?

如果上述有1个 Yes,可以考虑 MongoDB,2个及以上的 Yes,选择MongoDB绝不会后悔。

地理搜索、零散文件、对事务无要求的数据。正在用它替代mysql

应用范围和限制

MongoDB 的主要目标是在 key-value (键/值)存储方式(提供了高性能和高度伸缩性)以及传统的 RDBMS 系统(丰富的功能)架起一座桥梁,集两者的优势于一身。 MongoDB 适用范围如下:

  • 网站数据: Mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
  • 缓存:由于性能很高, Mongo 也适合作为信息基础设施的缓存层。在系统重启之后,由 Mongo 搭建的持久化缓存层可以避免下层的数据源过载。
  • 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
  • 高伸缩性的场景: Mongo 非常适合由数十或数百台服务器组成的数据库。 Mongo 的路线图中已经包含对 MapReduce 引擎的内置支持。
  • 用于对象及 JSON 数据的存储: MongoBSON 数据格式非常适合文档化格式的存储及查询。

MongoDB 当然也会有以下场景的限制:

  • 高度事物性的系统:例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
  • 传统的商业智能应用:针对特定问题的 BI 数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
  • 需要 SQL 的问题。

事务

MongoDB 4.0 引入的事务功能,支持多文档ACID特性

事务和副本集

在MongoDB中多文档事务操作只支持 副本集 的操作,关于在分片上的事务操作会在4.2版本中引入

存储引擎

在MongoDB中只有 WiredTiger 存储引擎才支持多文档事务操作,在 in-memoryMMAPv1存储引擎
中不支持多文档事务操作


相关api测试

语句可以不用 ; 结束

  • show dbs 所有数据库
  • db.version() 数据库版本
  • use aaa 使用aaa数据库
    • db 当前使用的数据库
    • db.getUsers() 当前数据库使用者
    • db.auth("root","123456") 认证
    • db.dropDatabase() 删除当前使用数据库

创建用户

使用 db.createUser 命名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> db.createUser(
{
user: "wilker",
pwd: "123456",
roles: [ { role: "readWrite", db: "myblog" },
{ role: "read", db: "myblog22" } ]
}
)

# 创建成功提示
Successfully added user: {
"user" : "wilker",
"roles" : [
{
"role" : "readWrite",
"db" : "myblog"
},
{
"role" : "read",
"db" : "myblog22"
}
]
}

创建数据库

1
2
3
4
> use myTest; // 1. use 一个不存在的 db 就是创建

> db.createCollection("account"); // 2. 显式创建
> 1

追加权限

db.grantRolesToUser("root", [{role:"readWrite", db:"admin"}]);

给 root 用户在 admin 追加 readWrite 权限, 这样远端就能 list 所有 collections 了


获取集合

下面两种方式都可以获取到集合, 然后进行操作

1
2
> db.trainer
> db.getCollection("trainer")

插入数据

col 集合中插入数据

1
2
3
4
5
6
7
8
> db.col.insert({title: 'MongoDB 教程', 
description: 'MongoDB 是一个 Nosql 数据库',
by: '菜鸟教程',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
});
WriteResult({ "nInserted" : 1 })

查询数据

  • 查询 col 集合中的所有数据

    1
    2
    > db.col.find()
    { "_id" : ObjectId("56064886ade2f21f36b03134"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }

聚合 group by

下边是aggregate()⽅法与mysql聚合类⽐

mongo聚合操作 SQL操作(函数) 说明
$match where 对数据进行条件搜索
$group group by 对数据进行分组聚合
$having having 对聚合后的数据进行过滤筛选
$project select 选择数据字段
$sort order by 对数据进行排序
$limit limit 限制数据返回数量
$sum sum()、count() 聚合统计数据字段

aggregate中$match、$group等操作被称为pipeline中的stage(阶段),它们提供了丰富的⽅法来筛选聚合数据,$match提供了$gt(>)、$lt(<)、$in(in)、$nin(not in)、$gte(>=)、$lte(<=)等等筛选符。

$group 按指定的表达式对⽂档进⾏分组,并将每个不同分组的⽂档输出到下⼀个阶段。输出⽂档包含⼀个_id字段,该字段按键包含不同的组。输出⽂档还可以包含计算字段,该字段保存由$group的_id字段分组的⼀些accumulator表达式的值。 $group不会输出具体的⽂档⽽只是统计信息。语法:

{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }

  • _id字段是必填的;但是,可以指定_id值为null来为整个输⼊⽂档计算累计值。
  • 剩余的计算字段是可选的,并使⽤运算符进⾏计算。

accumulator常⽤操作符:

名称 描述 sql类比
$avg 计算平均值 avg avg
$first 返回每组第⼀个⽂档,如果有排序,按照排序,如果没有按照默认的存储的顺序的第⼀个⽂档。 limit 0,1
$last 返回每组最后⼀个⽂档,如果有排序,按照排序,如果没有按照默认的存储的顺序的最后个⽂档。 -
$max 根据分组,获取集合中所有⽂档对应值得最⼤值。 max
$min 根据分组,获取集合中所有⽂档对应值得最⼩值。 min
$sum 计算总和 sum
$push 将指定的表达式的值添加到⼀个数组中。 -

db.collection.aggregate()是基于数据处理的聚合管道,每个⽂档通过⼀个由多个阶段(stage)组成的管道,可以对每个阶段的管道进⾏分组、过滤等功能,然后经过⼀系列的处理,输出相应的结果


启动配置

  1. 配置文件 mongod.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    systemLog:
    destination: file
    path: "/var/log/mongodb/mongod.log"
    logAppend: true

    storage:
    dbPath: "/var/mongodb/mydata"
    journal:
    enabled: true

    net:
    bindIp: 0.0.0.0
    port: 27017

    security:
    authorization: "enabled" # disabled
  2. 启动

    1
    # mongod --config /mytemp/mongod.conf

索引优化


explain 查看执行语句


常见问题

Q: 显示集合报错 : error listcollections failed

没有对数据库的读权限, 添加一个读写权限

1
2
3
4
5
6
> db.grantRolesToUser("root", [{role:"readWrite", db:"wekan"}]); # 给root用户添加wekan读写权限
> use wekan
> show collections
accountSettings # 有权限读写了
activities
...