admin 管理员组文章数量: 887038
2023年12月19日发(作者:commit的意思)
MongoDB开发使用手册
一.基础部分
MongDB简介
1. NOSQL历史和产生原因
原因: 互联网用户数的增长和用户参与互联网习惯的改变
1. 初始的静态内容网站,提供中心化的内容服务,
特点: 中心化,用户阅读内容
系统:Apache
2. 动态网页内容,电子商务和论坛网站出现。
特点: 用户访问动态内容,并提供少量内容
系统:Apache+Mysql+Php, IIS+ASP+SQLSERVER, IIS++SQLSERVER,
TOMCAT+JSP+ORACLE
3. 博客出现: 去中心化网站出现。
特点:Web2.0网站的雏形 用户阅读内容,并开始更多地参与网站的交互
系统: 高并发访问,数据库压力增大 Memcached 缓存的出现,并出现数据库集群的概念
4. 微博,淘宝等网站出现,以及云计算平台出现,如google,百度广告,等大规模系统
特点: 用户重复参与网站交互,和内容提供,而系统需要对用户行为进行分析
系统:支持高并发,及时响应,并能够实现分布式计算
NOSQL:Memcached, Redis, Hbase, 等NOSQL数据库,不仅仅是简单缓存,并能够提供分布式要求,包括复制,分片,水平分区,并提供复杂格式的数据存储
总结:
1. 高并发读写操作
普通关系型数据库,很难满足高并发读写的要求,上万次读写的需求
2. 海量数据存储
上亿用户产生大量数据,包括用户数据,访问日志,用户提供内容,用户状态记录等,这种海量数据的存储,关系型数据库已经很难满足,尤其是从海量数据中提取和汇总数据成为瓶颈
3. 高可用性和高扩展性
关系型数据库也能支持,同步复制,水平分区扩展,但维护工作相当繁杂,并很难做到热扩展
4. 内存操作(快速), 并发量高(非阻塞进程), 硬盘回写(数据完整和高效的平衡),备份和恢复
复制(高可用性,和连续服务), 分片(热扩展,海量数据) 操作简单(JSON),负载均衡,
分布式部署(局域网,和物理部分), 事务支持
2. 主流的NOSQL介绍
数据库类型
CouchDB
开发语言
Erlang
特性
特点:DB一致性,易于使用
使用许可: Apache
协议: HTTP/REST
双向数据复制
持续进行或临时处理
处理时带冲突检查
因此,采用的是master-master复制(见编注2)
MVCC - 写操作不阻塞读操作
可保存文件之前的版本
Crash-only(可靠的)设计
需要不时地进行数据压缩
视图:嵌入式 映射/减少
格式化视图:列表显示
支持进行服务器端文档验证
支持认证
根据变化实时更新
支持附件处理
因此,CouchApps(独立的 js应用程序)
需要 jQuery程序库
Redis C
特点:运行异常快
使用许可: BSD
协议:类 Telnet
1. 读写操作异常快
2. 较复杂的数据格式 sets, 链表,hash
3. 事务支持
4. 消息订阅 pub/sub
5. 主从同步复制
6. 硬盘回写
7. 第三方sharding支持
Mongodb C++
特点:保留了SQL一些友好的特性(查询,索引)。 1.大数据量查询和汇总
使用许可: AGPL(发起者: Apache)
协议: Custom, binary( BSON)
1. 支持javascript表达式
2. 硬盘回写
3. 主从复制和集群功能
4. 内建分片机制
5. 较快读写性能
2.分布式部署,和水平扩展
数据统计汇总
业务数据库,替代Mysql
适用于数据变化快且数据库大小可遇见(适合内存容量)的应用程序
应用场景
适用于数据变化较少,执行预定义查询,进行数据统计的应用程序。适用于需要提供数据版本支持的应用程序。
如CMS系统,数据统计汇总
股票价格、数据分析、实时数据搜集、实时通讯
配置下发,全局实时数据
6. 大格式数据支持
7.空数据库大约占 192Mb
8. 事务支持
Neo4j Java
特点:基于关系的图形数据库
使用许可: GPL,其中一些特性使用 AGPL/商业许可
协议: HTTP/REST(或嵌入在 Java中)
1.可独立使用或嵌入到 Java应用程序
2.图形的节点和边都可以带有元数据
3.很好的自带web管理功能
4.使用多种算法支持路径搜索
5.使用键值和关系进行索引
6.支持事务(用 Java api)
7.使用 Gremlin图形遍历语言
8.支持 Groovy脚本
9.支持在线备份,高级监控及高可靠性支持使用
HBase Java
特点:支持数十亿行X上百万列
使用许可: Apache
协议:HTTP/REST (支持 Thrift,见编注4)
1. 采用分布式架构 Map/reduce
2. 对实时查询进行优化
3. 高性能 Thrift网关
4. 通过在server端扫描及过滤实现对查询操作预判
5. 支持 XML, Protobuf, 和binary的HTTP
6. 对配置改变和较小的升级都会重新回滚
7. 不会出现单点故障
Memcache C
1. 快速
2. 简单
3. 分布式支持和热扩展
KV数据库
数据库辅助缓存
适用于偏好BigTable:)并且需要对大数据进行随机、实时访问的场合
报表,数据挖掘
适用于图形一类数据。这是 Neo4j与其他nosql数据库的最显著区别
例如:社会关系,公共交通网络,地图及网络拓谱
3.Mongodb概述
3.1.Mongodb 内部文件和内存管理
结构: Database,Collection,Document
数据库DB集合Collection1集合Collection2文档Document1文档Document2文档Document3文档document4
逻辑关系对比
Mongodb
Db(数据库)
Collection(集合)
Document(文档)
Field(列)
每个数据库都有相应的数据库文件
示例: 新建了两个数据库(test,test1),并在两个collection(user1,user2)分别插入记录
显示相关数据
[root@localhost db]# ls -l
-rwxr-xr-x 1 root root 5 12-23 17:07
-rw------- 1 root root 16777216 12-23 17:08 test.0
-rw------- 1 root root 33554432 12-23 17:08 test.1
-rw------- 1 root root 16777216 12-23 17:08 test1.0
-rw------- 1 root root 33554432 12-23 17:08 test1.1
-rw------- 1 root root 16777216 12-23 17:08
-rw------- 1 root root 16777216 12-23 17:08
drwxr-xr-x 2 root root 4096 12-23 17:08 _tmp
分别按两倍递增,16M,32M,64M,128M…..2G,最大为2G,所以mongodb单服务器和数据库最大存储上限为2G
内存管理方式
Mysql
Database(数据库)
Table(表)
Row(行)
Col(字段)
1. Mongod启动时,会载入相应文件到物理内存,并把内存管理交给系统,内存使用和结构如下所示,如果数据量很大,mongod启动的速度会较慢
2. 物理内存,虚拟内存,swap, MMAP
使用MMAP映射文件到虚拟内存,并映射虚拟内存到实际的物理内存
Linux内核stack进程MongodLinux内核stack进程MongodTest.0Test.1未分配Test1.0Test.1Test1.0Test1.1Test1.1…Null…Null
32bit 内存上限为 4G-1G(内核占用)-0.5堆栈 =2.5 即32位系统的内存可寻址上限是2.5G
62bit 内存上限为12T 所以mongodb的单数据库上限也相应的增加
所以32位系统mongod的单数据库文件上限为2G
3. 物理文件被分成相应的块,每个块之间使用双向链表来连接
Linux内核stack进程MongodTest.0基本信息上一块指针下一块指针…
4. 内存按照16M,32M,64M…2G递增方式进行分配,会预留相应的内存空间
这是mongod会大量消耗内存的原因,即使一条记录,也会占用16M的内存空间,并且还不包括所预先分配的内存空间
这样的机制有利于防止较小的数据库浪费过多的磁盘空间,同时又能保证较大的数据库有相应的预留空间使用。
5. 名字空间索引,保存着相应的文件索引
每一条记录保存着相应的名字空间(包括collection的关键信息)
Linux内核stackUse1进程MongodUser2Test.0User3Test.Test1.0Test1.0Test1.11. name: user12. status: size, extend 起始地址 extend 终止地址5. index data地址…
6. 内存的分配,新加入的数据,看是否有适合的空闲内存块可以分配,如果没有则增加新的数据块
Mongodb需要定期来进行数据压缩,以释放掉相应的空闲内存,移动相应数据,把内存碎片整理成完整的内存块,以便于进行重新分配。
>repairDatabase()
>mand({ compact : 'yourCollection' });
分别进行数据库的压缩和单个集合的压缩
3.2.BSON数据格式
索引的概念—数据库
NullMongdb的安装和配置
1. 下载
/downloads
Linux ,windows, mac osx, solaris 编译和Source版安装
建议选择64bit版本,能够支持更大的数据存储,32bit仅仅支持最大2G的文件
建议选择编译版本安装,能够适应特性的硬件和系统平台,能够进行定制和配置安装,而且效率较高,不会出现兼容性错误,建议在产生环境使用
一般选择在linux平台安装
2. 在linux平台安装
步骤1: 解压
>cp /usr/local
>tar zxvf
步骤2: 建立相应的数据库目录和日志目录
>cd /usr/local/mongodb
>mkdir db
>mkdir logs
步骤3: 启动mongodb
>cd /usr/local/mongodb/bin
>/usr/local/mongodb/bin/mongod –dbpath=/usr/local/mongodb/db
–logpath=/usr/local/mongodb/logs/ --fork
步骤4:安装相应的服务
> vi /etc/
添加 /usr/local/mongodb/bin/mongod –dbpath=/usr/local/mongodb/db
–logpath=/usr/local/mongodb/logs/ --fork
步骤5 连接mongod
>mongo
步骤6 查看mongo日志
>vi /usr/local/mongodb/logs/
3. Windows平台安装
步骤1: 解压到指定目录 如c:
步骤2: 建立相应的数据库目录和日志目录
>c:mongodbdb
>c:mongodblogs
步骤3: 启动mongodb
>cd c:mongodbbin
>mongod –dbpath=c:mongodbdb –logpath=c:
步骤4:安装相应的服务
> mongod –dbpath=c:mongodbdb –logpath=c:
>net start mongodb
步骤5 连接mongod
>mongo
步骤6 查看mongo日志
4. Linux 源码安装(待完善)
5. 配置参数说明
基本配置
--------------------------------------------------------------------------------
--quiet # 安静输出
--port arg # 指定服务端口号,默认端口27017
--bind_ip arg # 绑定服务IP,若绑定127.0.0.1,则只能本机访问,不指定默认本地所有IP
--logpath arg # 指定MongoDB日志文件,注意是指定文件不是目录
--logappend # 使用追加的方式写日志
--pidfilepath arg # PID File 的完整路径,如果没有设置,则没有PID文件
--keyFile arg # 集群的私钥的完整路径,只对于Replica Set 架构有效
--unixSocketPrefix arg # UNIX域套接字替代目录,(默认为 /tmp)
--fork # 以守护进程的方式运行MongoDB,创建服务器进程
--auth # 启用验证
--cpu # 定期显示CPU的CPU利用率和iowait
--dbpath arg # 指定数据库路径
--diaglog arg # diaglog选项 0=off 1=W 2=R 3=both 7=W+some reads
--directoryperdb # 设置每个数据库将被保存在一个单独的目录
--journal # 启用日志选项,MongoDB的数据操作将会写入到journal文件夹的文件里
--journalOptions arg # 启用日志诊断选项
--ipv6 # 启用IPv6选项
--jsonp # 允许JSONP形式通过HTTP访问(有安全影响)
--maxConns arg # 最大同时连接数 默认2000
--noauth # 不启用验证
--nohttpinterface # 关闭http接口,默认关闭27018端口访问
--noprealloc # 禁用数据文件预分配(往往影响性能)
--noscripting # 禁用脚本引擎
--notablescan # 不允许表扫描
--nounixsocket # 禁用Unix套接字监听
--nssize arg (=16) # 设置信数据库.ns文件大小(MB)
--objcheck # 在收到客户数据,检查的有效性,
--profile arg # 档案参数 0=off 1=slow, 2=all
--quota # 限制每个数据库的文件数,设置默认为8
--quotaFiles arg # number of files allower per db, requires --quota
--rest # 开启简单的rest API
--repair # 修复所有数据库run repair on all dbs
--repairpath arg # 修复库生成的文件的目录,默认为目录名称dbpath
--slowms arg (=100) # value of slow for profile and console log
--smallfiles # 使用较小的默认文件
--syncdelay arg (=60) # 数据写入磁盘的时间秒数(0=never,不推荐)
--sysinfo # 打印一些诊断系统信息
--upgrade # 如果需要升级数据库
* Replicaton 参数
--------------------------------------------------------------------------------
--fastsync # 从一个dbpath里启用从库复制服务,该dbpath的数据库是主库的快照,可用于快速启用同步
--autoresync # 如果从库与主库同步数据差得多,自动重新同步,
--oplogSize arg # 设置oplog的大小(MB)
* 主/从参数
--------------------------------------------------------------------------------
--master # 主库模式
--slave # 从库模式
--source arg # 从库 端口号
--only arg # 指定单一的数据库复制
--slavedelay arg # 设置从库同步主库的延迟时间
* Replica set(副本集)选项:
--------------------------------------------------------------------------------
--replSet arg # 设置副本集名称
* Sharding(分片)选项
--------------------------------------------------------------------------------
--configsvr # 声明这是一个集群的config服务,默认端口27019,默认目录/data/configdb
--shardsvr # 声明这是一个集群的分片,默认端口27018
--noMoveParanoia # 关闭偏执为moveChunk数据保存?
6. 配置文件示例
#
#where to log
logpath=/var/log/mongo/
logappend=true
# fork and run in background
fork = true
#port = 27017
dbpath=/var/lib/mongo
# Enables periodic logging of CPU utilization and I/O wait
#cpu = true
# Turn on/off security. Off is currently the default
#noauth = true
#auth = true
# Verbose logging output.
#verbose = true
# Inspect all client data for validity on receipt (useful for
# developing drivers)
#objcheck = true
# Enable db quota management
#quota = true
# Set oplogging level where n is
# 0=off (default)
# 1=W
# 2=R
# 3=both
# 7=W+some reads
#oplog = 0
# Diagnostic/debugging option
#nocursors = true
# Ignore query hints
#nohints = true
# Disable the HTTP interface (Defaults to localhost:27018).
#nohttpinterface = true
# Turns off server-side scripting. This will result in greatly limited
# functionality
#noscripting = true
# Turns off table scans. Any query that would do a table scan fails.
#notablescan = true
# Disable data file preallocation.
#noprealloc = true
# Specify .ns file size for new databases.
# nssize =
# Accout token for Mongo monitoring server.
#mms-token =
# Server name for Mongo monitoring server.
#mms-name =
# Ping interval for Mongo monitoring server.
#mms-interval =
# Replication Options
# in replicated mongo databases, specify here whether this is a slave or master
#slave = true
#source =
# Slave only: specify a single database to replicate
#only =
# or
#master = true
#source =
# Address of a server to pair with.
#pairwith =
# Address of arbiter server.
#arbiter =
# Automatically resync if slave data is stale
#autoresync
# Custom size for replication operation log.
#oplogSize =
# Size limit for in-memory storage of op ids.
#opIdMem =
7. 停止mongodb
命令方式
>use admin
switched to db admin
>wnServer()
进程方式
ps –aef | grep mongod
kill -2
简单的数据操作
1. 切换并产生数据库
>use tutorise
在切换数据库时,如果数据库不存在,则直接产生数据库
2. 插入相应数据
>({username:'gaoyu'})
当collection不存在时,产生相应的数据库集,并插入相应数据
此过程会分配内存,并产生相应的文件,同时插入数据,所以第一次插入的速度会相对较慢
3. 显示所有数据
>()
{ "_id" : ObjectId("4ef311a1776fbc2bc7dd038f"), "username" : "gaoyu" }
没有附带相应的查询条件,所以会显示所有的数据条目
4. 继续插入数据
>({username:'Jone'})
>()
并统计整体collection 的数据条目数
解释相应的ObjectID,这是在Collection中唯一的数值,是mongodb自动进行分配的,HASH
5. 进行相应的查询
>({username:'gaoyu'})
查询username 为gaoyu的所有记录,
find(查询匹配表达式) 查询匹配表达式也是JSON形式,字段:'内容'
6. 数据更新
数据更新分为两种形式,包括简单数据更新,和复杂数据更新
简单数据更新
>({username:'gaoyu'},{$set:{countty:'tianjin'}})
({更新查询条件},{$set:{更新内容}})
更新符合查询条件的内容,如果字段不存在,则添加相应字段并进行更新
更新复杂的数据
( {username: "Jone"},
{ $set:{favorites:
{
cities: ["Chicago", "Cheyenne"],
movies: ["Casablanca", "The Sting"]
}
}
})
7. 删除数据
进行Collection的整体删除
>()
仅仅是移除数据从user,而并不是进行物理删除,如果要进行实际的物理删除可以使用
>()
进行实际的物理删除
8. 产生相应的索引
1. 插入相应的200000条数据
>for(i=0;i<2000000;i++){
>...({num:i});
>...}
2. 查询相应的数据
>()
>()
>200000
3. 进行相应数据范围查询
( {num: {"$gt": 199995 }} ).explain()
{
{
"cursor" : "BasicCursor",
"nscanned" : 200000,
"nscannedObjects" : 200000,
"n" : 4,
"millis" : 136,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
1. "cursor" : "BasicCursor", 表示仅仅使用了基础游标,对整表进行了相应的扫描
2. "nscanned" : 200000, 扫描记录数为200000
3. "n" : 4, 得到四条匹配记录
4. "millis" : 136, 用时 136毫妙
5. "indexOnly" : false, 是否使用索引
常用工具集
MongoDB在bin目录下提供了一系列有用的工具,这些工具提供了MongoDB在运维管理上方便。
bsondump: 将bson格式的文件转储为json 格式的数据
mongo: 客户端命令行工具,其实也是一个js 解释器,支持js 语法
mongod: 数据库服务端,每个实例启动一个进程,可以fork 为后台运行
mongodump/ mongorestore: 数据库备份和恢复工具
mongoexport/ mongoimport: 数据导出和导入工具
mongofiles: GridFS管理工具,可实现二制文件的存取
mongos: 分片路由,如果使用了sharding 功能,则应用程序连接的是mongos而不是
mongosniff: 这一工具的作用类似于tcpdump,不同的是他只监控MongoDB相关的包请求,并且是以指定的可读性的形式输出
mongostat: 实时性能监控工具
推荐客户端工具
1. MongoVUE
/
一个windows下的客户端管理工具,对于未来的功能有一个长长的roadmap。
2. rock_mongo
它的描述是“Best PHP based MongoDB administration GUI tool” ,最近 MongoDB 的讨论组上很多人推荐。
/p/rock-php/
3. phpMoAdmin
二.mongoDB应用开发
MongoDB机制
组成
mongodb分为客户端,和服务器两部分,分别按照Mongodb的通信协议负责不同的职责,共同完成mongodb的操作
客户端:
1. 负责生成_id hash,按照相应的规则
2. 把客户端提交的内容JSON转化为BSON(二进制的JSON)
3. 和服务端通过TCP Socket进行通讯,把客户端提交内容传递给服务器
4. 接受服务端的返回,并把BSON反序列化为JSON
_ID
生成一个全局唯一的ID
4c342312 238d3c 19bc
4位时间戳 机器ID 进程ID
BSON
/display/DOCS/Mongo+Wire+Protocol
000001
计数器
进行相应的处理
Mongodb进行相应处理,包括查询和插入操作,并返回相应的值(BSON)
设计mongodb数据库
包含以下主题
设计数据库的标准,能够满足应用程序的需求
能够表现,一对一,一对多,多对多模式
1. 电子商务数据库示例
商品表
products =
{_id: new ObjectId("4c4b1476238d3b4dd5003981"),
slug: "book-barrow-9092",
sku: "9092",
name: "mongodb 开发手册",
descriptuon: "NOSQL数据库开发",
detail{
weight: 230,
weight_unit: "g",
count: 200,
manufacturer: "Tech",
color: "red"
},
totel_view: 4,
average_view: 4.5
price{
retail: 45,
sale:40
}
price_history{[
{
retail:45
sale:40
start_date: new Date(2011,11,1),
end_date: new Date(2011,12,25)
},
{
retail:45
sale:30
start_date: new Date(2011,10,1),
end_date: new Date(2011,10,31)
}
]},
category_main: new ObjectId("6a5b1476238d3b4dd5000049"),
tags:["mongodb","computer","book","NOSQL"]
}
产生slug唯一索引,保证sku在products的唯一性
>Index({sku: 1}, {unique: true})
>(name:”redis 开发手册”,
>…sku: 9092,
>…slug: “redis cookbook”
>…safe:true
>…}
系统会拒绝进行相应的插入操作,因为唯一索引的问题
1. Field和字段的概念有所区别,能够递归包含
设计mongodb数据库
包含以下主题
设计数据库的标准,能够满足应用程序的需求
能够表现,一对一,一对多,多对多模式
1. 电子商务数据库示例
商品表
products =
{_id: new ObjectId("4c4b1476238d3b4dd5003981"),
slug: "book-barrow-9092",
sku: "9092",
name: "mongodb 开发手册",
descriptuon: "NOSQL数据库开发",
detail{
weight: 230,
weight_unit: "g",
count: 200,
manufacturer: "Tech",
color: "red"
},
totel_view: 4,
average_view: 4.5
price{
retail: 45,
sale:40
}
price_history{[
{
retail:45
sale:40
start_date: new Date(2011,11,1),
end_date: new Date(2011,12,25)
},
{
retail:45
sale:30
start_date: new Date(2011,10,1),
end_date: new Date(2011,10,31)
}
]},
category_main: new ObjectId("6a5b1476238d3b4dd5000049"),
tags:["mongodb","computer","book","NOSQL"]
}
产生slug唯一索引,保证sku在products的唯一性
>Index({sku: 1}, {unique: true})
>(name:”redis 开发手册”,
>…sku: 9092,
>…slug: “redis cookbook”
>…safe:true
>…}
系统会拒绝进行相应的插入操作,因为唯一索引的问题
1. Field和字段的概念有所区别,能够递归包含
2. 关系型数据库设计原则:
范式但出于性能和特殊要求,数据库设计的规则会发生相应的改变
模式1: 一对多模式
和mysql不同,由于mongodb能够保存相应的子文档,所以表现一对多关系可以采用两种方式,分别是内嵌式和关联式
内嵌式表达:
关联式:
广告订单--广告投放
广告订单:
{
_id: ObjectId("4d650d4cf32639266022018d"),
name:"宝洁广告订单1",
start_date:"120909404",
end_date:"133949494",
...
}
广告投放:
{
_id: ObjectId("4d650d4cf32639266022ac01"),
}
name:"北京推广1",
order_id:"4d650d4cf32639266022018d",
...
内嵌式:
{ title: "How to soft-boil an egg",
steps: [
{ desc: "Bring a pot of water to boil.",materials: ["water", "eggs"] },
{ desc: "Gently add the eggs a cook for four minutes.", materials: ["egg timer"]},
{ desc: "Cool the eggs under running water." },
]
}
1. 由于组织结构不同,处理一对多关系,不同于关系型数据库仅仅采用一种关联模式,而存在两种模式
2. 当关联不属于从属关系,而且存在双向查询,则采用关联模式,并需要进行关联键进行索引
3. 当两者属于包含关系,则采用内嵌方式,并且被包含对象不会经常变化,并不会进行双向查询,或对被包含对象进行其他关联查询
4. 是否属于从属关系,是否会进行双向查询
模式2: 多对多关联
由于mongodb不存在连接查询,所以仅仅存在一种方式,即内嵌数组方式
产品--类目
products
{
_id: ObjectId("4d650d4cf32639266022018d"),
title:"mongodb 开发手册"
category_ids:[
ObjectId("4d6574baa6b804ea563c132a"),
ObjectId("4d6574baa6b804ea563c459d")
],
...
}
category
{
_id: ObjectId("4d6574baa6b804ea563c132a"),
title:"技术",
...
}
category
{
_id: ObjectId("4d6574baa6b804ea563c459d"),
title:"NOSQL",
...
}
1. 采用内嵌数据的方式表达相应的关联
2. 内嵌数据放在那里,决定于查询的方向频率,如果查询类目下所属产品的频率,高于查询产品所包含的类目,则应该把关联键放在产品下
3. 因为分别需要一步和两步
4. 为加速查询,关联键需要添加索引
模式3: 树
{
}
{
}
{
_id: ObjectId("4d692b5d59e212384d95001"),
depth: 0,
path:null,
created: ISODate("2011-02-26T17:18:01.251Z"),
username: "plotinus",
body:"Who was Alexander the Great's teacher?",
thread_id: ObjectId("4d692b5d59e212384d95223a")
_id: ObjectId("4d692b5d59e212384d951002"),
depth: 1,
path:"4d692b5d59e212384d95001",
created: ISODate("2011-02-26T17:21:01.251Z"),
username: "asophist",
body:"It was definitely Socrates.",
thread_id: ObjectId("4d692b5d59e212384d95223a")
_id: ObjectId("4d692b5d59e212384d95003"),
depth: 2,
path:"4d692b5d59e212384d95001:4d692b5d59e212384d951002",
created: ISODate("2011-02-26T17:21:01.251Z"),
username: "daletheia",
body:"Oh It was actually Aristotle!",
thread_id: ObjectId("4d692b5d59e212384d95223a")
}
1. 添加相应的索引 Index({thread_id: 1})
Index({path: 1}
2. 查询整个树 ({thread_id: ObjectId("4d692b5d59e212384d95223a")})
3. 查询某节点的子节点 ({path: /^4d692b5d59e212384d95001/})
模式4 树2
{
_id: ObjectId("4d692b5d59e212384d95003"),
comment_id: 1,
nsleft:0,
nsright:0,
...
}
1. 采用左右数的方式能够支持更快速的树形遍历
2. 方便的进行索引
3. 但缺点是更新的删除操作需要一定的算法和附加的写操作
模式5:可变属性
mongodb可以很好的支持可变属性
如两个产品类型
{
_id: ObjectId("4d669c225d3a52568ce07646")
sku: "ebd-123"
name:"飞利浦耳机",
type:"小电器",
attrs: {
color: "银色",
freq_low: 20,
freq_hi: 22000,
weight: 0.5
}
{
}
}
_id: ObjectId("4d669c225d3a52568ce07646")
sku: "ssd-456"
name:"SSD卡",
type:"硬件",
attrs: {
interface: "SATA",
capacity: 1.2 * 1024 * 1024 * 1024,
rotation: 7200,
form_factor: 2.5
}
第二种方式
{ _id: ObjectId("4d669c225d3a52568ce07646")
sku: "ebd-123"
name:"耳机2",
type:"小家电",
attrs: [
{n: "color", v: "silver"},
{n: "freq_low", v: 20},
{n: "freq_hi", v: 22000},
{n: "weight", v: 0.5}
]
}
1. 表现可变属性可以使用两种方式,1:直接输用内嵌对象的方式,2:使用名值对数组
2. 采用哪种方式有两个决定因素,分别是属性变化是否可知,包括属性类型和属性数量
3. 方式1:便于检索,和显示,而方式2: 会有更大的通讯信息量,但便于进行索引
4. Index({"attrs.n": 1, "attrs.v": 1})
5. Index({"_low": 1, "_hi": 1},{sparse: true})
模式6:不要忽视索引
索引对于mongodb的优化起到决定性作用,而通过分析应用程序的查询条件,进而建立相应的索引,对于系统的
优化起到决定性作用,不要忽视索引
Index("title":1}
模式7: 不要混杂
由于mongodb的特性,所以容易引导把不同的对象,放在同一document中,所以需要大家尽量把不同的对象放在不同的文档中
便于后期的扩展和索引的优化,
模式8:多值属性
可以参考模式1
不要采用相应的值直接写入
高级数据库操作
数据类型
string, integer, boolean, double, null, array, and object.
日期:
>x =new Date()
>d=new ISODate()
>r()
>th()
>
数据库
建立数据库
产生数据库,转到相应数据,并产生数据库
1. 判断数据库是否存在,如果不存在则在硬盘产生相应的文件
>use magento
删除数据库
删除相应的数据库,和数据库内部的集合,并删除相应的索引,同时删除相应物理文件
>use magento
>tabase()
查看数据库状态
> ()
{
"collections" : 3,
"objects" : 10004,
"avgObjSize" : 36.005,
"dataSize" : 360192,
"storageSize" : 791296,
"numExtents" : 7,
"indexes" : 1,
"indexSize" : 425984,
"fileSize" : 201326592,
"ok" : 1
}
系统命令
aces 显示所有名字空间
s 显示所有索引
e stores database profiling information.
显示数据库用户
s 显示所有源
集合
新建集合
产生集合,并分配相应的空间
>Collection(“users”)
>Collection("users", {size: 20000})
显示集合列表
>show collections
修改集合名称
>Collection(“newName”)
>mand({renameCollection:”oldname”,to:”e”})
Capped Collection 集合
概念
1.
2.
3.
4.
Capped集合是定长文档,记录集的长度是定长,定数量的
Capped集合的数据库尺寸是预先定制的,如1024K
我们可以预算得到capped记录集的document数,
Capped 的按先后顺序进行插入,如果文档数溢出,则丢弃最早的记录,先进先出的定长队列,并且有系统自动实现
5. 不存在索引,插入和提取速度都相当快
应用:
1. 日志系统: 保留最早日志,并自动抛弃较早日志,或写入到其他集合中
2. 最近浏览: 保存用户最近浏览的记录
3. 最新内容: 保存指定数量的最新内容
产生
>Collection("mycoll", {capped:true, size:100000})
>();
>();
>().sort({"$natural": -1})
系统集合
系统名字空间
> ();
{ "name" : "ts" }
{ "name" : "s" }
{ "name" : "ts.$_id_" }
{ "name" : "s", "options" :
{ "create": "s", "capped": true, "size": 1024 } }
系统索引
> ();
{ "name" : "_id_", "ns" : "ts", "key" : { "_id": 1 } }
索引
Mongo索引采用btree方式,回顾mysql索引
索引是?
Mongodb索引的组织形式?
索引操作
索引的概念
聚类索引,一般索引,btree索引 btree+索引
聚类
Btree
Btree+
索引效果
1. 插入相应的200000条数据
>for(i=0;i<2000000;i++){
>...({num:i});
>...}
2. 查询相应的数据
>()
>()
>200000
3. 进行相应数据范围查询
( {num: {"$gt": 199995 }} ).explain()
{
{
"cursor" : "BasicCursor",
"nscanned" : 200000,
"nscannedObjects" : 200000,
"n" : 4,
"millis" : 136,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
1. "cursor" : "BasicCursor", 表示仅仅使用了基础游标,对整表进行了相应的扫描
2. "nscanned" : 200000, 扫描记录数为200000
3. "n" : 4, 得到四条匹配记录
4. "millis" : 136, 用时 136毫妙
5. "indexOnly" : false, 是否使用索引
> Index({num:1})
> ( {num: {"$gt": 199995 }} ).explain()
建立索引
>Index({num:1},{background : true,unique:true, sparse:true,
dropDups:true})
>Index( { "" : 1, "" : 1 } );
查看索引
> exes()
>()
复合索引
Index({j:1, name:-1});
a,b,c
可以使用在下列情况
a
a,b
a,b,c
唯一索引
Index({firstname: 1, lastname: 1}, {unique: true});
删除索引
dexes();
dex({x: 1, y: -1})
重建索引
x()
插入
> doc = { author : 'joe', created : new Date('03/28/2009') }
> (doc);
修改
如果增加相应的field,则把修改记录移动到尾部,并进行field添加和修改
Update操作
( criteria, objNew, upsert, multi )
criteria:条件
objNew:对象
upsert:如果不存在,插入
multi:多值匹配
Set
{ $set : { field : value } }
> ({"name" : "joe"},
... {"$set" : {"favorite book" :
... ["cat's cradle", "foundation trilogy", "ender's game"]}} )
Unset
{ $unset : { field : 1} }
>({name:”test”},{“$unset”:{score:1}})
Inc
{ $inc : { field : value } }
> > ({"game" : "pinball", "user" : "joe"},
... {"$inc" : {"score" : 10000}})
仅仅能够应用在数值类型的field,也可以使用负值,相当于-
push
{ $push : { field : value } }
> ({name:”gaoyu”},{“$push”:{favor:”tv”}})
>({name:”gaoyu”},{“$push”:{favor:”basketball”}})
如果字段存在,并且是数组类型,则压入相应的值到数据,如果不存在,则创建数组字段,并压入值
pushAll
{ $pushAll : { field : value_array } }
> ({name:”gaoyu”},{“$push”:{favor:[“tv1”,”tv2”]}})
压入一个数组,如果字段存在,则压入所有值,不存在,则添加数组,不是数组类型报错
pop
{ $pop : { field : 1 } } { $pop : { field : -1 } }
> ({name:”gaoyu”},{“$pop”:{favor:1}})
>({name:”gaoyu”},{“$pop”:{favor:1}})
弹出最后一个值,堆栈,知道数组为空,如果不是数组类型则报错
Pull
{ $pull : { field : {
弹出符合条件的值
Rename
修改字段名
{ $rename : { old_field_name : new_field_name } }
锁
({score: {$gt: 60}, $atomic: true}, {$set: {pass: true}}, false, true)
分片不支持加锁
FindandModify
修改,并返回相应值
> ( {
name: "Next promo",
inprogress: false, priority:0,
tasks : [ "select product", "add inventory", "do placement"]
} );
> ( {
name: "Biz report",
inprogress: false, priority:1,
tasks : [ "run sales report", "email report" ]
} );
> ( {
name: "Biz report",
inprogress: false, priority:2,
tasks : [ "run marketing report", "email report" ]
} );
> job = dModify({
query: {inprogress: false, name: "Biz report"},
sort : {priority:-1},
update: {$set: {inprogress: true, started: new Date()}},
new: true
});
{
"_id" : ...,
"inprogress" : true,
"name" : "Biz report",
"priority" : 2,
"started" : "Mon Oct 25 2010 11:15:07 GMT-0700 (PDT)",
"tasks" : [
"run marketing report",
"email report"
]
}
删除
删除整体数据,但不删除索引
>()
删除指定条件的数据
>({username:”test”})
>({_id:”assdd”}) 推荐
>(object) 不推荐
删除指定的集合,并删除索引,速度比单条删除记录要快
>();
删除锁
>( { rating : { $lt : 3.0 }, $atomic : true } )
删除会在内存和文件产生碎片,通过repairDatabase(),来整理内存碎片
查询
查询整体数据集合
>();
没有给出条件就是查询完全数据集,但客户端仅仅返回50条记录,如果继续查看请键入it
根据条件进行查询
>({product_id:117})
>数据库.(查询条件), 其中查询条件为JSON格式
组合条件查询
> ({"product_id":117, "category_id":3})
>数据库.({查询条件1, 查询条件2}) 两个条件之间使用,分割
返回指定的字段
>({product_id: 117},{product_id:1,category_id:1})
格式:({查询条件},{field1:1,field2:1}) 第二个参数显示需要显示的字段
>({product_id: 117},{product_id:1,category_id:1,_id:0})
排除某些字段不进行显示
范围查询
>({product_id:{$gt:100}}) $gt 查询product_id 大于100的记录
>({product_id:{$lt:100}}) $lt 查询product_id 小于100的记录
>({product_id:{$gt:100,$lt:200}}) $gt,$lt组合使用,查询product_id 大于100且小于200的记录
$lt:小于 $lte:小于等于 $gt 大于 $gte 大于等于 $ne不等于
In查询
$in 查询值在指定的集合内进行匹配
$nin 对不在指定集合条件的记录进行匹配
>({product_id: {$in:[121,128,129]}})
> ({product_id: {$nin:[121,128,129]}})
或查询
$or 满足两个条件之一的记录进行相应的匹配
>({$or:[{product_id:121},{category_id:3}]})
>({$or:[{product_id:{$in:[121,128,129]},{category_id:3}}]
Limit和skip
限制返回的记录集数
>().limit(n)
掠过指定的记录集个数,从第n+1条记录开始显示
>().skip(n)
Sort排序
分别按照指定顺序进行排序,类似于1正序,-1倒序
>().sort({username:1,age:-1})
>().limit(50).skip(50).sort({username:1})
随机值查询
>var random = ()
>result = e({“random”:{“$gt”:random})
Null查询
>(“z”:{“$exists”:true})
使用$exists查询指定字段为null值的记录,而不能使用 xxx:null
数组查询
单值匹配
>({fruit:”apple” })
多值匹配
>({fruit:{all:[“apple”,”banana”]})
***Sql查询的映射图
Sql
SELECT * FROM users
SELECT a,b FROM users
SELECT * FROM users WHERE age=33
SELECT a,b FROM users WHERE age=33
Mongodb
()
({},{a:1,b:1})
({age:33})
({age:33},{a:1,b:1})
SELECT * FROM users WHERE age=33 ORDER ({age:33}).sort({name:1})
BY name
SELECT * FROM users WHERE age>33
SELECT * FROM users WHERE age!=33
({age:{“$gt”:33}})
({age:{“$ne”:33}})
SELECT * FROM users WHERE name LIKE ({name:”Joe”})
"%Joe%"
SELECT * FROM users WHERE name LIKE ({name:^Joe})
"Joe%"
SELECT * FROM users WHERE age>33 AND ({age:{“$gt”:33},age:{“lte”:40}})
age<=40
SELECT * FROM users ORDER BY name DESC
SELECT * FROM users WHERE a=1 and b='q'
SELECT * FROM users LIMIT 10 SKIP 20
SELECT * FROM users WHERE a=1 or b=2
SELECT * FROM users LIMIT 1
SELECT order_id FROM orders o,
order_line_items li WHERE
_id=_id AND =12345
聚合
Count计数
>()
().sort({name:-1})
({a:1,b:”q”})
().limit(10).skip(20)
( { $or : [ { a : 1 } , { b : 2 } ] } )
e()
({"":12345},{_id:1})
对collection的记录进行相应的计数,计数对于统计数据库记录数,并进行相应的分页
GRIDFS
简介
GridFS主要是用来存储大型文件,如高清图片,视频,或文本等
安装PHP客户端
Linux
$ tar zxvf mongodb-mongdb-php-driver-
$ cd mongodb-mongodb-php-driver-
$ phpize
$ ./configure
$ sudo make install
编辑,添加
Extension=””
应用案例
1. 案例1 电子商务
产品表:
{
_id: new ObjectId("4c4b1476238d3b4dd5003981"),
slug:"wheel-barrow-9092",
sku: "9092",
name:"Extra Large Wheel Barrow",
description: "Heavy ",
details: {
weight: 47,
weight_units: "lbs",
model_num: 4039283402,
manufacturer: "Acme",
color: "Green"
},
total_reviews: 4,
average_review: 4.5,
pricing: {
retail: 589700,
sale:489700,
},
price_history: [
{
retail: 529700,
sale: 429700,
start: new Date(2010, 4, 1),
end: new Date(2010, 4, 8)
},
{
retail: 529700,
sale: 529700,
start: new Date(2010, 4, 9),
end: new Date(2010, 4, 16)
},
],
category_ids: [
new ObjectId("6a5b1476238d3b4dd5000048"),
new ObjectId("6a5b1476238d3b4dd5000049")
],
main_cat_id: new ObjectId("6a5b1476238d3b4dd5000048"),
tags:["tools", "gardening", "soil"],
}
Index({slug: 1}, {unique: true})
类目表
doc =
{ _
id: new ObjectId("6a5b1476238d3b4dd5000048"),
slug:"gardening-tools",
ancestors: [
{
name: "Home",
_id: new ObjectId("8b87fb1476238d3b4dd500003"),
slug: "home"
},
{ name: "Outdoors",
_id: new ObjectId("9a9fb1476238d3b4dd5000001"),
slug: "outdoors"
}
],
parent_id: new ObjectId("9a9fb1476238d3b4dd5000001"),
name:"Gardening Tools",
description: "Gardening gadgets galore!",
}
订单表
doc =
{ _
id: ObjectId("6a5b1476238d3b4dd5000048")
user_id: ObjectId("4c4b1476238d3b4dd5000001")
state: "CART",
line_items: [
{
_id: ObjectId("4c4b1476238d3b4dd5003981"),
sku: "9092",
name: "Extra Large Wheel Barrow",
quantity: 1,
pricing: {
retail: 5897,
sale: 4897,
}
},
{
_id: ObjectId("4c4b1476238d3b4dd5003981"),
sku: "10027",
name: "Rubberized Work Glove, Black",
quantity: 2,
pricing: {
retail: 1499,
sale: 1299
}
}
],
shipping_address: {
street: "588 5th Street",
city:"Brooklyn",
state: "NY",
zip: 11215
},
sub_total: 6196
}
用户表
{
_id: new ObjectId("4c4b1476238d3b4dd5000001"),
username: "kbanker",
email:"********************",first_name: "Kyle",
last_name: "Banker",
hashed_password: "bd1cfa194c3a603e7186780824b04419",
addresses: [
{
name: "home",
street: "588 5th Street",
city:"Brooklyn",
state: "NY",
zip: 11215
},
{
name: "work",
street: "1 E. 23rd Street",
city:"New York",
state: "NY",
zip: 10010
}
],
payment_methods: [
{
name: "VISA",
last_four: 2127,
crypted_number: "43f6ba1dfda6b8106dc7",
expiration_date: new Date(2014, 4)
}
]
}
应用1: 查询某地区的用户,使用邮政编码进行查询
>({ “”:{“$lt”:12334,”gt”:11123}})
应用2: 查询买过某商品的用户,并显示用户的详细信息
user_ids = (
{
'line_': "9092",
purchase_date: {'$gt': new Date(2009, 0, 1)}
},
{user_id: 1, _id: 0}
).toArray().map(
function(doc) {
return doc['_id']
}
)
users = ({_id: {$in:user_ids}})
问题: 查询0-30的用户
问题: 返回单条购物超过97元的订单
问题: 返回颜色不是黑色和蓝色的商品
问题: 返回标签式 garden和3c的产品
问题: 返回制造商是ACM,并标签不是 garden的商品
问题: 返回last_name 不以B为开头的用户
问题: 返回颜色为蓝色和绿色的商品
问题: 返回颜色为蓝色,或制造商是ACM的商品
问题: 返回属性中带有颜色的商品
问题: 返回制造商id为432的商品
问题: 返回标签为soil的商品
问题: 返回第一个标签为0的商品
问题: 返回第一个地址中state为NY的用户
问题: 返回地址中state为NY的用户
问题: 返回地址.name为home,并在state为NY的用户
问题: 返回有三个地址的用户
问题: 返回用户ID对3取余余1的用户
问题: 返回sku大于1000的商品,并仅仅显示商品名
问题:商品价格倒序
问题:用户按注册日期倒序,并掠过100,取10条记录
三.mongoDB分布式集群
分片
1. 分片的原因:
由于海量数据的原因,单台服务器不能满足数据存储的需求,包括硬盘和内存
数据库读写负载的增加,单台服务器不能满足读/写并发的需求,通过分担相应的负载到不同的服务器上,来满足需求。 尤其是写负载的情况
海量数据的数据提取和汇总的瓶颈
最终需要通过分片,满足海量数据,高并发写的需求
最终核心:把单中心节点的数据和计算,分散到不同分布式节点,每个节点仅仅对路由中心负责,而客户端仅仅知道路由中心
2. 分片实现方式(水平分区)
手动方式(客户端程序控制)
中间键方式: mysql+amoba
数据系统内置的分片机制,mysql+cluster,mongodb内置分片
程序方式:
写入时,由程序按照算法写入到不同服务器DB客户端读取时,根据算法进行路由,定位到不同服务器,如果汇集需要进行分布提取,并汇总DB2DB3
优点: 完全控制,能够自己来定义写入和读取的规则
缺点:
程序复杂性提高
分布式计算,并进行汇总的效率不易进行优化
算法比较固定,如取余,分段,或业务逻辑分片
难于扩展,和删除节点,由于存在数据迁移
调整负载和数据分布不容易
维护工作繁杂,难于热扩展
分片对于客户端是不透明,并且是紧耦合的
DB客户端中间键DB2DB3通过中间键配置,来把中间键作为代理,实现自动的分片
优点:
缺点:
分片对客户端透明
采用配置方式来设定分片方式
分片策略可定制
减少客户端的开发工作
性能损失
节点扩展,数据迁移问题
如果分布算法不平衡,存在节点负载不均衡的问题
3. 何时进行分片
开始时不进行分片,只有当需要分片时才采取分片策略
单机内存不足
Mongod已经不能满足高并发写需求
大数据量读写
4. Mong分片的目的
5. 分片的步骤
步骤1:建立配置服务器
>./mongod –dbpath=/usr/local/mongodb/db –port=2000 –fork
说明:
配置服务器负责储mongos的相应配置,包括分片规则和分片数据对应关系
如同启动普通服务器
步骤2:建立mongos服务
>./mongos –port=3000 –configdb localhost:2000 –logpath=/usr/local/mongodb/logs/
–fork
步骤3:建立相应分片节点
节点1
> ./mongod --port=1000 --dbpath=/usr/local/mongodb/db
--logpath=/usr/local/mongodb/logs/ –fork
节点2
> ./mongod --port=1000 --dbpath=/usr/local/mongodb/db
--logpath=/usr/local/mongodb/logs/ –fork
版权声明:本文标题:MongoDB开发使用手册 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1702981588h438332.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论