一、简介
Nosql
NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。
关系型数据库:遵循ACID原则
# 1、A (Atomicity) 原子性
原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。
比如银行转账,从A账户转100元至B账户,分为两个步骤:1)从A账户取100元;2)存入100元至B账户。这两步要么一起完成,要么一起不完成,如果只完成第一步,第二步失败,钱会莫名其妙少了100元。
# 2、C (Consistency) 一致性
一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。
例如现有完整性约束a+b=10,如果一个事务改变了a,那么必须得改变b,使得事务结束后依然满足a+b=10,否则事务失败。
# 3、I (Isolation) 独立性
所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。
比如现有有个交易是从A账户转100元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的100元的。
# 4、D (Durability) 持久性
持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。
分布式系统
分布式系统(distributed system)由多台计算机和通信的软件组件通过计算机网络连接(本地网络或广域网)组成。
分布式系统是建立在网络之上的软件系统。正是因为软件的特性,所以分布式系统具有高度的内聚性和透明性。
因此,网络和分布式系统之间的区别更多的在于高层软件(特别是操作系统),而不是硬件。
分布式系统可以应用在在不同的平台上如:Pc、工作站、局域网和广域网上等。
分布式计算的优缺点:
# 优点
可靠性(容错) :
分布式计算系统中的一个重要的优点是可靠性。一台服务器的系统崩溃并不影响到其余的服务器。
可扩展性:
在分布式计算系统可以根据需要增加更多的机器。
资源共享:
共享数据是必不可少的应用,如银行,预订系统。
灵活性:
由于该系统是非常灵活的,它很容易安装,实施和调试新的服务。
更快的速度:
分布式计算系统可以有多台计算机的计算能力,使得它比其他系统有更快的处理速度。
开放系统:
由于它是开放的系统,本地或者远程都可以访问到该服务。
更高的性能:
相较于集中式计算机网络集群可以提供更高的性能(及更好的性价比)。
# 缺点
故障排除: :
故障排除和诊断问题。
软件:
更少的软件支持是分布式计算系统的主要缺点。
网络:
网络基础设施的问题,包括:传输问题,高负载,信息丢失等。
安全性:
开发系统的特性让分布式计算系统存在着数据的安全性和共享的风险等问题。
什么是Nosql?
NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
为什么使用NoSQL?
今天我们可以通过第三方平台(如:Google,Facebook等)可以很容易的访问和抓取数据。用户的个人信息,社交网络,地理位置,用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘,那SQL数据库已经不适合这些应用了, NoSQL数据库的发展也却能很好的处理这些大的数据。
RDBMS vs NoSQL
# RDBMS
- 高度组织化结构化数据
- 结构化查询语言(SQL) (SQL)
- 数据和关系都存储在单独的表中。
- 数据操纵语言,数据定义语言
- 严格的一致性
- 基础事务
# NoSQL
- 代表着不仅仅是SQL
- 没有声明性查询语言
- 没有预定义的模式
-键 - 值对存储,列存储,文档存储,图形数据库
- 最终一致性,而非ACID属性
- 非结构化和不可预知的数据
- CAP定理
- 高性能,高可用性和可伸缩性
二、MongoDB简介
**注意:**使用前修改bin目录下配置文件mongodb.cfg,删除最后一行的’mp’字段
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
MongoDB的默认数据库为"db",该数据库存储在data目录中。
MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
启动服务与终止服务
net start mongodb
ner stop mongodb
创建管理员用户
use admin
db.createUser({user:"shj",pwd:"123456",roles:["root"]})
使用账号密码连接mongodb
mongo -u shj -p 123456 --authenticationDatabase admin
简单库操作
show dbs # 展示所有数据库
db # 显示当前数据库对象名或集合。
use 数据库名 # 如果存在则切换到指定的库,不存在就创建一个库
# 我们刚刚用use创建的库使用show dbs是没有显示的,需要先插入一条数据才行
# db.mongo.insert({"name":"宁姚"})
# MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。
db.dropDatabase() # 删除数据库,删除前先切换到要删除的库
db.collection.drop() # 删除集合
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
-
admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
-
local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
-
config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
表
# 使用前先切换数据库 show tables 查所有的表 db.table1.insert({'b':2}) 增加表(表不存在就创建) db.table1.drop() 删表
文档
{"site":"www.baidu.com", "name":"百度"}
# 需要注意的是:
文档中的键/值对是有序的。
文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
MongoDB区分类型和大小写。
MongoDB的文档不能有重复的键。
文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
插入文档
# 插入文档,MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下:
db.COLLECTION_NAME.insert(document)
# 例:col是集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档
'''
db.col.insert({title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: 'MongoDB中文网',
url: 'http://www.mongodb.org.cn',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
})'''
db.col.find() # 查看已插入的文档
# 我们也可以将数据定义为一个变量,然后执行插入操作
'''
document={title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: 'Mongodb中文网',
url: 'http://www.mongodb.org.cn',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
};
db.col.insert(document)
'''
# 插入文档你也可以使用 db.col.save(document) 命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。
更新文档
# 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 :可选,抛出异常的级别。
# 例:更新标题
db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
db.col.find().pretty()
# 如果要更新多条相同的文档,需要知道multi=true
db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true})
删除文档
# 删除所有数据
db.col.remove({})
db.col.find()
# 删除一条数据
db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)
查询文档
db.COLLECTION_NAME.find()
# find() 方法以非结构化的方式来显示所有文档。
# 如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
db.col.find().pretty()
集合
集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表格。
集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
{"site":"www.baidu.com"} {"site":"www.google.com","name":"Google"} {"site":"www.runoob.com","name":"菜鸟教程","num":5}
连接到默认数据库
# 有密码(admin/123456)
mongodb://admin:123456@localhost/
# 无密码
mongo
MongoDB 与 RDBMS Where 语句比较
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | {<key>:<value> } | db.col.find({"by":"菜鸟教程"}).pretty() | where by = '菜鸟教程' |
小于 | {<key>:{$lt:<value>}} | db.col.find({"likes":{$lt:50}}).pretty() | where likes < 50 |
小于或等于 | {<key>:{$lte:<value>}} | db.col.find({"likes":{$lte:50}}).pretty() | where likes <= 50 |
大于 | {<key>:{$gt:<value>}} | db.col.find({"likes":{$gt:50}}).pretty() | where likes > 50 |
大于或等于 | {<key>:{$gte:<value>}} | db.col.find({"likes":{$gte:50}}).pretty() | where likes >= 50 |
不等于 | {<key>:{$ne:<value>}} | db.col.find({"likes":{$ne:50}}).pretty() | where likes != 50 |
MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,及常规 SQL 的 AND 条件。
db.col.find({key1:value1, key2:value2}).pretty()
OR
db.col.find({ $or: [ {key1: value1}, {key2:value2}]}).pretty()
AND和OR联合使用
db.col.find({"likes": {$gt:50}, $or: [{"by": "Mongodb中文网"},{"title": "MongoDB 教程"}]}).pretty()
三、常用操作
基础操作
mongo 进入MongoDB命令行客户端
cls 清除当前命令行客户端内容
show dbs 列出所有的数据库
show databases 列出所有的数据库
use mldn 切换数据库,此处mldn只是随意取的数据库名称,此切换可以随意切换到没有创建的数据库中,一旦添加数据,此数据库会跟随创建。必须。
db.dropDatabase() 删除当前数据库
db.dropDatabase('mldn') 删除指定数据库
db.createCollection('tmp') 创建集合,相当于数据库中创建表,非必须
db.getCollection('tmp') 拿到集合,相当于拿到表在进行操作,非必须,学习时可省略
show collections 查看所有集合,查看所有表
db.tmp.drop() 删除名为tmp的集合(表)
db.getCollection('tmp') 删除名为tmp的集合(表)
db.user.update({'_id':2},{"$set":{"name":"WXX",}}) 改数据
db.user.deleteOne({ 'age': 8 }) 删第一个匹配
db.user.deleteMany( {'addr.country': 'China'} ) 删全部匹配
db.user.deleteMany({}) 删所有
增加、插入数据
db.tmp.insert({json对象});//单条插入
db.tmp.insert([{json对象},{}]);//批量插入
//db.tmp.insert({姓名: “张三“,sex:1,age:19});
删除
db.tmp.remove({json对象,部分条件});
//db.tmp.remove({age:19});
查询
db.tmp.find(); 查询所有
db.tmp.findOne(); 查看一个
查询核心语法:db.集合名称.find({查询条件}[,{设置显示的字段}])[.pretty()];//美化操作可选
//db.tmp.find({url:"mldn-14"},{_id:0}).pretty() //_id对应的值为0不显示,为1表示显示
// db.tmp.findOne({url:"mldn-14"},{_id:0})//无pretty()
关系运算
大于($gt)、小于($lt)、大于等于($gte)、小于等于($lte)、等于($eq)
//db.tmp.find({age:{"$gt":1,"$lt":99}}).pretty();
不是($ne)
//db.tmp.find({age:{“$ne”:99}});
db.user.find({'name':'alex'}) 查xx==xx
db.user.find({'name':{"$ne":'alex'}}) 查xx!=xx
db.user.find({'_id':{'$gt':2}}) 查xx>xx
db.user.find({"_id":{"$gte":2,}}) 查xx>=xx
db.user.find({'_id':{'$lt':3}}) 查xx<xx
db.user.find({"_id":{"$lte":2}}) 查xx<=xx
逻辑运算
与($and)、或($or)、非($not、$nor)、
//db.tmp.find({age:{‘$gte’:19,’$lte’:20}}).pretty();
//db.tmp.find({age:{‘$not’:19}})(错误)
//db.tmp.find({age:{‘$ne’: 19}});
//db.tmp.find({‘$or’:[{age:{‘$gt’:19}},{score:[‘$lt’:90]}]})//或者
//db.tmp.find({‘$nor’:[{age:{‘$gt’:19}},{score:[‘$lt’:90]}]})//或者取反
求模($mod)
//db.tmp.fiind({age:{‘$mod’:[20,1]}})//年龄除以20余1的数据 求模
范围查询
在范围之中($in)、不在范围之中($nin)
// db.tmp.find({age:{'$in':[1,2,3,4,5]}})在范围
// db.tmp.find({age:{'$nin':[1,2,3,4,5]}})不在范围
数组查询
//db.tmp.insert({name:'大神11',age:11,course:['语文','数学','英语']})
//db.tmp.insert({name:'大神11',age:11,course:['数学','英语']})
//db.tmp.insert({name:'大神11',age:11,course:['语文','英语']})
# 数组操作符:$all、$size、$sliice、$elemMatch
//同时参加语文和数学的人
//db.tmp.find({'course':{'$all':['语文','数学']}})//查询课程中包含语文和数学的
//db.tmp.find({name:{'$all':['大神11']}})//查询名字为大神11的
# 数组使用索引操作
//db.tmp.find({'course.1':'英语'})//查询课程数组索引为1的课程为英语的
# 数组长度查询
//db.tmp.find({'course':{'$size':2}})//查询课程选择了两门的
//db.tmp.find({'course':{'$size':2}},{course:{'$slice':[1,1]}})返回数组# # 指定长度数据
//[1,1] //从数组1开始,长度为1
# 嵌套查询
//db.tmp.insert({name:'11',age:11,course:['语文','数学','英语'],parents:[{name:'father',age:50,job:'工人'},{name:'mother',age:50,job:'工人2'}]})
//db.tmp.insert({name:'13',age:11,course:['数学','英语'],parents:[{name:'father',age:52,job:'处长'},{name:'mother',age:46,job:'工人aa'}]})
//db.tmp.insert({name:'12',age:11,course:['语文','英语'],parents:[{name:'father',age:53,job:'局长'},{name:'mother',age:30,job:'工人啊啊'}]})
//db.tmp.find({age:{'$gte':11},parents:{'$elemMatch':{'job':'局长'}}}).pretty();
# 判断某个字段是否存在 ($exists)
//db.tmp.find({age:{'$gte':11},parents:{'$exists':true}});//查询具有parents值的对象
//db.tmp.find({age:{'$gte':11},parents:{'$exists':false}});//查询不具有parents的对象
# 条件过滤 ($where)不能使用到索引,这个是JavaScript操作。
//db.tmp.find({'$where':'this.age>=11'});
//db.tmp.find(‘this.age>=11’)//where 的简化
// db.tmp.find({‘$where’:function(){return this.age>=11;}})
// db.tmp.find(function(){return this.age>=11;})
// db.tmp.find({'$and':[{'$where':'this.age>=11'},{'$where':'this.age<21'}]})
排序
# 排序函数($sort())、升序(1)、降序(-1)
# 自然排序,按照数据保存的先后排序($natural)
//db.tmp.find().sort({age:1}).pretty();
// db.tmp.find().sort({'$natural':-1}).pretty();
分页
# skip(n)跳过多少条记录
# limit(n)每次取多少条记录
//db.tmp.find().skip(0).limit(5).sort({'age':-1}).pretty();
# count()查询总数
//db.tmp.find({条件}).count();
//db.tmp.count({条件},{参数});
参数: limit:限制最大数量
skip:跳过数量
hint:索引名称
maxTimeMS:允许查询的最大时间,单位ms
readConcern:读取级别
四、pymongo
client = pymongo.MongoClient(host=host,port=port, username=username, password=password)
db = client["db_name"] 切换数据库
table = db['表名']
table.insert({}) 插入数据
table.remove({}) 删除数据
table.update({'_id':2},{"$set":{"name":"WXX",}}) 改数据
table.find({}) 查数据
测试
# -*- coding: utf-8 -*-
# @Author : Sunhaojie
# @Time : 2019/8/13 19:33
import pymongo
import time
host = '127.0.0.1'
port = 27017
username = 'shj'
password = '123456'
client = pymongo.MongoClient(
host=host,
port=port,
username=username,
password=password
)
db = client['shj']
print(db)
table = db['table1']
print(table)
data1 = {
'_id': time.time(),
'name': 'lwb'
}
data2 = {
'_id': 13442355256246243,
'name': 'lxx'
}
data3 = {
'_id': 1232445555555324,
'name': 'shj'
}
# 插入数据
# table.insert([data1, data2, data3])
# 删除数据
# table.remove({"name": "lxx"})
# table.remove({'name': {'$gt': 'shj'}})
# 更新
# table.update({"name":"lwb"},{"$set":{"name":"lsb", "salary":100000}})
# table.update_many({"name":"yxp"},{'$set':{"salary":20000}})
# 查询
for i in table.find({"salary": {"$gt": 10000}}):
print(i)
获取集合和数据库列表
import pymongo
MONGO_CONFIG = {
'host': '127.0.0.1',
'port': 27017,
'username': 'mongouser',
'password': '',
'auth_db': 'admin',
'database': 'yapi',
}
mongo_client = pymongo.MongoClient(
host=MONGO_CONFIG['host'],
port=MONGO_CONFIG['port'],
username=MONGO_CONFIG['username'],
password=MONGO_CONFIG['password'],
authsource=MONGO_CONFIG['auth_db']
)
# 查看数据库列表
db_list = mongo_client.list_database_names()
print(db_list)
# 查看集合列表
db = mongo_client[MONGO_CONFIG['database']]
table_list = db.list_collection_names()
print(table_list)
# 查看集合user中的数据
collection = db['user']
result = collection.find().batch_size(10)
for i in result:
print(i)