mongodb应用
一.概述
NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
github:https://github.com/mongodb/mongo
二.安装
在Ubuntu下可直接安装,官网推荐安装mongodb-org:
sudo apt-get install -y mongodb-org
也可在官网下载tar包后安装https://www.mongodb.com/download-center#community:
curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.6.tgz # 下载 tar -zxvf mongodb-linux-x86_64-3.0.6.tgz # 解压 mv mongodb-linux-x86_64-3.0.6/ /usr/local/mongodb # 将解压包拷贝到指定目录 export PATH=<mongodb-install-directory>/bin:$PATH
创建数据库目录
MongoDB的数据存储在data目录的db目录下,但是这个目录在安装过程不会自动创建,所以你需要手动创建data目录,并在data目录中创建db目录。
注意:/data/db 是 MongoDB 默认的启动的数据库路径(--dbpath)。
mkdir -p /data/db
MongoDB后台管理shell
mongo是MongoDB自带的交互式JavaScript shell,用来对MongoDB进行操作和管理的交互式环境。
MongoDBDB允许远程访问
MongoDB 安装完之后,默认情况下是不会开启外网访问权限和登录验证:
$ sudo sed -i '/bindIp/{s/127.0.0.1/0.0.0.0/}' /etc/mongod.conf $ sudo sed -i '/^#security/a\security:\n authorization: enabled' /etc/mongod.conf
或者增加启动参数--bind_ip_all。
mongod --dbpath ./db --bind_ip_all
mongodb web用户界面
MongoDB 提供了简单的 HTTP 用户界面。 如果你想启用该功能,需要在启动的时候指定参数 --rest 。注意:该功能只适用于 MongoDB 3.2 及之前的早期版本。
$ ./mongod --dbpath=/data/db --rest
MongoDB 的 Web 界面访问端口比服务的端口多1000。如果你的MongoDB运行端口使用默认的27017,你可以在端口号为28017访问web用户界面,即地址为:http://localhost:28017。
三.基础概念
1.数据库
一个mongodb中可以建立多个数据库。MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
show dbs:显示数据库列表
db:显示当前操作的数据库
use <db_name>:连接一个指定的数据库
数据库命名规则:满足以下条件的任意UTF-8字符串。
>>不能是空字符串(“”)。 >>不能含有空格、点号、$、/、\和\0(空字符) >>应全部小写 >>最多64字节
有些数据库名时保留的,可以直接访问这些有特殊作用的数据库:
>>admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
>>local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
>>config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
2.文档(Document):行
文档是一组键值(key-value)对(即 BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型。
{"site":"www.runoob.com", "name":"菜鸟教程"}
文档中的键/值对是有序的。
文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
MongoDB区分类型和大小写。
MongoDB的文档不能有重复的键。
文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
文档键命名规范:
>>键不能含有\0 (空字符)。这个字符用来表示键的结尾。 >>.和$有特别的意义,只有在特定环境下才能使用。 >>以下划线"_"开头的键是保留的(不是严格要求的)。
3. 集合(collection):table
集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表格。
集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
当第一个文档插入时,集合才会被创建。
合法的集合名
>>集合名不能是空字符串""。 >>集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。 >>集合名不能以"system."开头,这是为系统集合保留的前缀。 >>用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。
capped collections
Capped collections 就是固定大小的collection。Capped collections 是高性能自动的维护对象的插入顺序。它非常适合类似记录日志的功能。和标准的 collection 不同,你必须要显式的创建一个capped collection,指定一个 collection 的大小,单位是字节。collection 的数据存储空间值提前分配的。
Capped collections 可以按照文档的插入顺序保存到集合中,而且这些文档在磁盘上存放位置也是按照插入顺序来保存的,所以当我们更新Capped collections 中文档的时候,更新后的文档不可以超过之前文档的大小,这样话就可以确保所有文档在磁盘上的位置一直保持不变。
由于 Capped collection 是按照文档的插入顺序而不是使用索引确定插入位置,这样的话可以提高增添数据的效率。MongoDB 的操作日志文件 oplog.rs 就是利用 Capped Collection 来实现的。
db.createCollection("mycoll", {capped:true, size:100000})
要注意的是指定的存储大小包含了数据库的头信息。
>>在 capped collection 中,你能添加新的对象。 >>能进行更新,然而,对象不会增加存储空间。如果增加,更新就会失败 。 >>使用 Capped Collection 不能删除一个文档,可以使用 drop() 方法删除 collection 所有的行。 >>删除之后,你必须显式的重新创建这个 collection。 >>在32bit机器中,capped collection 最大存储为 1e9( 1X109)个字节。
4. 元数据
数据库的信息是存储在集合中。它们使用了系统的命名空间:dbname.system.*
在MongoDB数据库中名字空间<dbname>.system.*是包含多种系统信息的特殊集合(Collection),如下:
dbname.system.namespaces 列出所有名字空间。
dbname.system.indexes 列出所有索引。
dbname.system.profile 包含数据库概要(profile)信息。
dbname.system.users 列出所有可访问数据库的用户。
dbname.local.sources 包含复制对端(slave)的服务器信息和状态。
对于修改系统集合中的对象有如下限制:
在{{system.indexes}}插入数据,可以创建索引。但除此之外该表信息是不可变的(特殊的drop index命令将自动更新相关信息)。
{{system.users}}是可修改的。 {{system.profile}}是可删除的。
5.数据类型
几个重要的数据类型说明如下:
ObjectId
ObjectId类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:
前 4 个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时 接下来的 3 个字节是机器标识码 紧接的两个字节由进程 id 组成 PID 最后三个字节是随机数
MongoDB 中存储的文档必须有一个 _id 键。这个键的值可以是任何类型的,默认是个 ObjectId 对象。由于 ObjectId 中保存了创建的时间戳,所以你不需要为你的文档保存时间戳字段,你可以通过 getTimestamp 函数来获取文档的创建时间:
> var newObject = ObjectId() >newObject.getTimestamp() ISODate("2017-11-25T07:21:10Z")
ObjectId 转为字符串:
>newObject.str
5a1919e63df83ce79df8b38f
时间戳
BSON 有一个特殊的时间戳类型用于 MongoDB 内部使用,与普通的 日期 类型不相关。 时间戳值是一个 64 位的值,其中:
前32位是一个 time_t 值(与Unix新纪元相差的秒数)
后32位是在某秒中操作的一个递增的序数
在单个 mongod 实例中,时间戳值通常是唯一的。
在复制集中, oplog 有一个 ts 字段。这个字段中的值使用BSON时间戳表示了操作时间。
注:BSON 时间戳类型主要用于 MongoDB 内部使用。在大多数情况下的应用开发中,你可以使用 BSON 日期类型。
日期
表示当前距离 Unix新纪元(1970年1月1日)的毫秒数。日期类型是有符号的, 负数表示 1970 年之前的日期。
> var mydate1 = new Date() //格林尼治时间 > mydate1 ISODate("2018-03-04T14:58:51.233Z") >typeof mydate1 object > var mydate2 = ISODate() //格林尼治时间 > mydate2 ISODate("2018-03-04T15:00:45.479Z") >typeof mydate2 object
这样创建的时间是日期类型,可以使用 JS 中的 Date 类型的方法。
返回一个时间类型的字符串:
> var mydate1str = mydate1.toString() > mydate1str Sun Mar 04 2018 14:58:51 GMT+0000 (UTC) >typeof mydate1str string
或者
>Date() Sun Mar 04 2018 15:02:59 GMT+0000 (UTC)
6.数据库操作
连接数据库
可以使用 MongoDB shell 或PHP 来连接 MongoDB。
标准 URI 连接语法:
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
• mongodb:// 这是固定的格式,必须要指定。
• username:password@ 可选项,如果设置,在连接数据库服务器之后,驱动都会尝试登陆这个数据库
• host1 必须的指定至少一个host, host1 是这个URI唯一要填写的。它指定了要连接服务器的地址。如果要连接复制集,请指定多个主机地址。
• portX 可选的指定端口,如果不填,默认为27017
• /database 如果指定username:password@,连接并验证登陆指定数据库。若不指定,默认打开 test 数据库。
• ?options 是连接选项。如果不使用/database,则前面需要加上/。所有连接选项都是键值对name=value,键值对之间通过&或;(分号)隔开。如:authSource指定通过admin库进行登录认证。
linux下可直接用mongo连接数据库:
usage: mongo [options] [db address] [file names (ending in .js)] db address can be: foo foo database on local machine 192.168.0.5/foo foo database on 192.168.0.5 machine 192.168.0.5:9999/foo foo database on 192.168.0.5 machine on port 9999 192.168.0.5:9999 database on 192.168.0.5 machine on port 9999
$ mongo --quiet "mongodb://127.0.0.1:27017"
$ mongo --quiet mongodb://root:'iam59!z$'@127.0.0.1:27017/iam_analytics?authSource=admin
mongo命令行的js文件有语法要求,一个已知为不能使用“use db"命令切换数据库,应使用"db.getSiblingDB('db')"。
一个示例参考:https://github.com/edgexfoundry/docker-edgex-mongo/blob/master/init_mongo.js。
db=db.getSiblingDB('authorization')
db.createUser({ user: "admin",pwd: "password",roles: [ { role: "readWrite", db: "authorization" } ]});
创建数据库
db
显示当前使用的数据库
show dbs
显示所有数据库
use datebase_name
如果数据库不存在,则创建数据库,否则切换到指定数据库。
若此时执行showdbs看不到刚创建的数据库,要显示它,需要向数据库插入一些数据。
> use gateway switched to db gateway >db gateway > show dbs admin 0.000GB config 0.000GB local 0.000GB >db.gateway.insert({"name":"chinamobile"}) WriteResult({ "nInserted" : 1 }) > show dbs admin 0.000GB config 0.000GB gateway 0.000GB local 0.000GB
MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。注意: 在 MongoDB 中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。
删除数据库
db.dropDatabase()
删除当前数据库,默认为 test,你可以使用db命令查看当前数据库名。
7. 集合操作
创建集合
db.createCollection(name, options)
参数说明:
• name: 要创建的集合名称
• options: 可选参数, 指定有关内存大小及索引的选项
在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。
创建固定集合mycol,整个集合空间大小 6142800 KB, 文档最大个数为 10000 个。
>db.createCollection("mycol", { capped : true, autoIndexId : true, size : 6142800, max : 10000 } ) { "ok" : 1 }
当插入一些文档时,MongoDB 会自动创建集合。
>db.gateway.insert({"name":"chinamobile"}) WriteResult({ "nInserted" : 1 }) >db gateway > show collections gateway
显示集合
show collections
删除集合
db.collection_name.drop()
无参数;如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
8. 文档操作
文档的数据结构和JSON基本一样。
所有存储在集合中的数据都是BSON格式。
BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。
插入
db.COLLECTION_NAME.insert(document)
也可将数据定义为一个变量,如下:
> doc1=({"title":"wang","date":"20190508"}) { "title" : "wang", "date" : "20190508" } >db.gateway.insert(doc1) WriteResult({ "nInserted" : 1 })
插入文档你也可以使用db.col.save(document) 命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。
更新
MongoDB 使用 update() 和 save() 方法来更新集合中的文档。
update() 方法用于更新已存在的文档。语法格式如下:
db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> } )
参数说明:
• query : update的查询条件,类似sql update查询内where后面的。
• update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
• upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
• multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
• writeConcern :可选,抛出异常的级别。
通过update()方法更新标题(title):
>db.gateway.update({"title":"wang"},{$set:{"title":"cm"}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true。
>db.col.update({'title':'wang'},{$set:{'title':'cm'}},{multi:true})
save() 方法通过传入的文档来替换已有文档。语法格式如下:
db.collection.save( <document>, { writeConcern: <document> } )
参数说明:
•document : 文档数据。
•writeConcern :可选,抛出异常的级别。
删除
db.collection.remove( <query>, { justOne: <boolean>, writeConcern: <document> } )
参数说明:
•query :(可选)删除的文档的条件。
•justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
•writeConcern :(可选)抛出异常的级别。
如果你只想删除第一条找到的记录可以设置 justOne 为 1,如下所示:
>db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)
如果你想删除所有数据,可以使用以下方式(类似常规 SQL 的 truncate 命令):
>db.col.remove({})
查询
MongoDB 查询文档使用 find() 方法。find() 方法以非结构化的方式来显示所有文档。
db.collection.find(query, projection)
db.gateway.find()
•query :可选,使用查询操作符指定查询条件
•projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值,只需省略该参数即可(默认省略)。
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
>db.col.find().pretty()
pretty() 方法以格式化的方式来显示所有文档。
>db.col.update({'title':'wang'},{$set:{'title':'cm'}},{multi:true})
四. 交叉编译mongodb
mongodb设计为大数据存储使用,目前支持arm-64,但不支持arm,网络上有介绍编译的方法,但目前多次测试均未成功(一运行均出现段错误)。
http://facat.github.io/cross-compile-mongodb-for-arm.html Cross compile mongodb for arm
http://pansila.github.io/posts/ae66dec5/ Cross compile mongodb for 32bit arm
https://github.com/mattlord/mongo-embedded-sample
https://github.com/Barryrowe/mongo-arm
参考:
1. https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/
2. http://www.runoob.com/mongodb/mongodb-linux-install.html runoob