MongoDB
MongoDB背景
MongoDB是一个很有意思的数据库,一个介于关系型数据库和非关系型数据库之间,但它是(NoSQL)非关系数据库且功能最丰富,最接近关系的数据库,它的数据就是存放在内存中,对数据的操作大部分在内存中,但MongoDB并不是单纯的内存数据库,MongoDB是由C++编写的,是一个基于分布式文件存储开源数据库系统,它的存在就是能够为WEB应用提供 可扩展、高性能 存储数据解决方案.
什么是NoSQL?
NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。它指的是非关系型数据库, 数据库发展史上里程碑的出现,是对于不同的传统的关系型数据库的统称,常见的有Redis,MongoDB,HBase,NoSql,Cloudant...
它主要用于存储超大规模的数据,比如(新浪,谷歌,Facebook等公司都存储用户收集庞大的数据),这些数据存储不需要固定的模式,无法多余操作就可以横向扩展,现今我们可以通过第三平台(baidu,谷歌等..)可以容易访问和抓取数据,用户的个人信息,社交网络,地理位置,用户生成的数据,操作日志成倍增加,如果需要对这些数据进行挖掘分析,SQL型数据库的机制便不适合这些应用,NoSQL数据库能通过分布式系统分布式计算的优点可以处理这些无比庞大的数据.
MongoDB的存储方式和持久化
它以一种直观文档的方式存储数据,就像javascript中的JSON格式,在数据存储的时候它自动为文档增加了序列化的操作,最终存进磁盘的其实是一种BSON的格式;
既然是内存数据库就牵扯到持久化的问题了,MongoDB的所有数据实际上是存放在硬盘上的,所有操作的数据通过mmap的方式映射到内存中的一个区域,然后MongoDB就这区域进行数据修改,避免了硬盘操作,mmap系统上的内容通过操作系统flush到硬盘上,如果,MongoDB在内存中修改了数据后,mmap数据flush到硬盘之前,系统宕机了,数据就会丢失。
MongoDB的应用场景
项目开始初始阶段的时候,数据结构无法确定,这时MongoDB可以考虑优先推荐,相比关系型数据库MySQL,更容易扩展,为代码的扩展带来的极大的方便.但是业务繁多,要求极高的话,它便不适用了,因为它不支持事务,也就是说数据之间的关系复杂话,表关系的一对多,和多对多出现将会难以处理.
MongoDB的优缺点集锦
#优点: 性能优越,快速!在一定量内存级别中MongoDB的性能是非常迅速的,它将热数据存储在物理内存中,使得热数据读写速度非常快; 高扩展 第三方支持丰富(就是在其他NoSQL中也具备优势); 弱一致性 保障用户了访问速度; 文档结构存储方式 更加快捷的获取数据,json的存储格式; 支持大容量存储,内置分布式系统GridFS,Shading #缺点: 最大的缺点就是不支持事务!!! 其次内存占用空间大; MongoDB 没有像MySQL成熟的一体化维护,会对后续开发运营造成影响.
MongoDB安装
- 首先下载一个MongoDB 的msi安装包.例如mongodb-win32-x86_64-2008plus-ssl-3.4.18-signed.msi
- 一键安装,安装完毕后找到对应bin目录
- 整理环境变量,将bin目录路径添加到Path中(C:\Program Files\MongoDB\Server\3.4\bin;)注意win7需要在bin后面加上 " ;"
- 在C盘目录下创建data/db目录
- 启动mongodb,打开cmd,mongod启动服务,再打开另外一个cmd窗口连接mongodb服务,输入mongo即可!注意保障这两个窗口开启,当然这是window下的环境!
MongoDB 语法和使用
基础用法
安装不再赘述,但是安装后需要配置好环境变量..
启动服务端 ---> 执行 mongod 命令
默认端口 : 27017; (redis:6379;mysq:3306)
应用连接 MongoDB 数据库 ---> 执行 mongo命令 进行本地数据库连接
常用操作 show databases 查看当前数据库服务中包含的数据库,磁盘中的数据库 use db_name 切换当前使用的数据库,如果该名称库不存在,会在内存中创建一个新的数据库. db 显示当前使用的数据库,指数据表名 show tables 查看当前数据库的表名, 磁盘中的数据表 db.表名 在内存中创建数据库表 db_name.insertOne({}) 因此写入数据才能将内存中数据库和数据表永久写入到磁盘中 增加数据: db.users.insert({'id':1,'name':'wva'}) 数据库.数据表.指令.({data}) 查询数据: db.users.find() 数据库.数据表.指令
MongoDB存储数据的结构 ---> 俗成大字典.
MongoDB支持的数据类型
ObjectId数据类型 自增id-不限定在数据库和数据表中 String 字符串类型 Int 不直接默认Int数字,Int32,Int64,注意:如果不指定Int,存储的就是Double Double 双精度浮点型 默认数字存储类型,(不存在float类型) Array 列表数据类型 list = [ ] Object 字典数据类型 dict = {} Date ISODate() 时间日期数据类型 Null None Boolean ture/false Timestamp 时间戳 不过通常为Double存储
MongoDB -- 增删改查
增 (使用了不存在的对象,即创建该对象 use db db.table)
//官方不推荐写法 3.2 加入新的insert写入方式 增加一条:db.th.insert({name:1}) 增加多条:db.th.insert([{name:1},{name:2},{name:3}]) // 官方推荐的写法: 增加一条:db.task.insertOne({}) // 返回 _id 增加多条:db.task.insertMany([{},{},{}]) // 返回 _ids
查
1.查询所有符合条件的: db.task.find({}) 2.查询一条符合条件的: db.task.findOne({}) 3.带条件查询: db.task.findOne({'age':18}) db.task.find({name:'lingling',age:18}) 并列条件查询,名字和年龄同时满足
改
//更新符合条件的数据,默认为第一条符合条件的数据:db.stu.update({}, {$set:{}}) 不推荐 //官方推荐 修改器 : $set 强制将某字段的value修改 更新第一条符合条件的数据:db.task.updateOne({age:18}, {$set:{"name":"xiaokeai"}}) 更新所有符合条件的数据 : db.task.updateMany({name:'xiaokeai'}, {$set:{age:18}}) 将所有叫小可爱的改成18岁 ..嘿嘿
删
// 官方不推荐 删除符合条件的所有数据:db.task.remove({}) //官方推荐写法: 删除一条符合条件的: db.task.deleteOne({'name':'shazi'}) 删除多条符合条件的: db.task.deleteMany({'name':'shazi'}) 删除所有数据: db.task.deleteMany({})
MongoDB和MySQL比对
MySQL | MongoDB | |
数据表 | table | Collections |
数据行 | row | Documents |
数据列 | 字段 | Field |
高级查询
//并列查询 db.Collection.find({Field:1,Field2:2}) //或查询 在不同字段查询或条件时使用$or db.Collection.find({$or:[{Field:1},{Field2:3}]}) db.stu.find({$or:[{age:99},{name:'turtle'}]}) 在相同字段情况下查询或条件时使用 $in db.Collection.find({Field:{$in:[1,2,3,4,5]}}) db.task.find({age:{$in:[9,18,27,19]}}) //Array查询 db.task.find({"hobby":"game"}) //数字比较符查询 $lt $lte $gt $gte $eq $ne //子集查询 $all db.task.find({list:{$all:[8,6,4,2]}}) //Object对象查询 db.task.find({'class.name':'person'})
高级修改
//强制修改字段 $set db.task.updateMany({name:'baby'}, {$set: {"age":10}}) //引用增加字段 $inc db.task.updateMany({}, {$inc: {"age":10}}) //强制删除某个字段 $unset db.task.updateMany({}, {$unset: {"age":30}})
针对Array操作
//增加操作 db.task.updateOne({name:"小可爱"},{$push:{"hobby":"memeda"}}) 由此可见 $push == append 效果 db.task.updateOne({name:"小可爱"},{$pushAll:{"hobby":['swim','walk','read']}}) $pushAll == extend 迭代添加 //删除操作(两种方式) db.task.updateOne({name:"小可爱"},{$pull:{"hobby":"read"}})此时$pull == remove 在更新的时候删除一个符合条件的
db.task.updateOne({name:"金角大王8"},{$pullAll:{"hobby":['swim','walk']}}) $pullAll == 删除每一个元素 $pop() 是删除列表中的第一个 (-1) 或者最后一个 db.stu.updateOne({name:"小可爱"},{$pop:{"hobby":1}}) 删除最后一个 db.task.updateOne({name:"小可爱"},{$pop:{"hobby":-1}}) 删除第一个元素 //更新操作 db.task.updateOne({name:"小可爱","hobby":'game'},{$set:{"hobby.$":"memeda"}}) 将hobby 中 的game修改成 memeda db.task.updateOne({name:"小亲亲","class.name":"python"},{$inc:{"class.$.score":99}}) 添加一个字段score 成绩进去
针对Object操作
db.stu.updateOne({name:"小亲亲"},{$unset:{"class.classtype":"yy"}}) db.stu.updateOne({name:"小亲亲"},{$set:{"class.classtype":"hh"}})
关键字
$的使用
$ 用来存储符合条件的元素下标索引
list = [1,2,3,4] 哪个元素 == 2 它的下标是多少 $就等于这个下标的数字
list[1] = "x小可爱"
list[$] = "小可爱"
limit skip sort的使用
limit 选取数据量 db.task.find().limit(10) 选取前10条数据查看 skip 跳过数据量 db.task.find().skip(10) 跳过前10条查看 sort 根据字段进行排序 db.task.find().sort(name:1/-1) 进行正序/倒序排列 //分页查看,每页查看3条数据 db.task.find().sort({'name':1}).skip(0).limit(3) db.task.find().sort({'name':1}).skip(3).limit(3) db.task.find().sort({'name':1}).skip(6).limit(3)
pymongo应用
python后端和MongoDB连接
import pymongo conn = pymongo.MongoClient('127.0.0.1',27017) #use db_name MONGO_DB = conn['test'] #创建test库并连接
pymongo用法
向数据库增加data MONGO_DB.users.insert_one({'name':'keke','age':2}) #写入一条数据 MONGO_DB.users.insert_many([{'name':'keke'},{'name':'pan'}]) #写入多条数据 res = MONGO_DB.users.insert_one({'name': 'yy', 'age': 38, 'hobby': ['aa', 'bb', 'cc']}) ress = MONGO_DB.users.insert_many([ { 'name': 1, 'package': [ {'name': '极光剑', 'act': 99}, {'name': '墨竹戒指', 'atc': 15}, ] }, { 'name': 2, 'package': [ {'name': '王者之剑', 'act': 999}, {'name': '麻痹戒指', 'atc': 15}, ] }, { 'name': 3, 'package': [ {'name': '双龙魔影剑', 'act': 199}, {'name': '海克斯戒指', 'atc': 15}, ] } ]) print(ress, dir(ress), ress.inserted_ids) """ <pymongo.results.InsertManyResult object at 0x0000000002ED65C8> ['_InsertManyResult__acknowledged', '_InsertManyResult__inserted_ids', '_WriteResult__acknowledged', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '_raise_if_unacknowledged', 'acknowledged', 'inserted_ids'] [ObjectId('5c9b6b722de0502ce0095985'), ObjectId('5c9b6b722de0502ce0095986'), ObjectId('5c9b6b722de0502ce0095987')] """ """查询数据库数据""" res = MONGO_DB.users.find_one({'age':2},{'_id':0}) print(res,type(res)) # 注意MongoDB自己序列化,因此取出来的是字典类型 ress = list(MONGO_DB.users.find({},{'_id':0})) #find({}) #取得除了_id的数据 得到的是一个生成器 for item in ress: print(item) res = list(MONGO_DB.users.find({"$or":[{'name':'pan'},{'age':2}]},{'_id':0})) #或查询 or res = list(MONGO_DB.users.find({'name':{'$in':['pan','keke']}})) #或查询 in print(res) """修改数据库数据""" MONGO_DB.users.update_one({"hobby":"bb","name":"yanlong"},{"$set":{"hobby.$":"xxoo"}}) #修改hobby bb为 xxoo MONGO_DB.users.update_one({'name':1},{'$push':{'package':{'name':'屠龙刀','act':1099}}}) #修改 name 1中package属性 '''删除数据库数据''' MONGO_DB.users.delete_many({}) #删除所有数据 MONGO_DB.users.delete_one({"name":3}) #删除该条数据 MONGO_DB.users.delete_many({"name":"keke"}) #删除所有name = keke的数据 """通过_id取数据 """ res = MONGO_DB.users.find_one({"name":1}) res["_id"] = str(res.get("_id")) res_json = json.dumps(res) print(res_json) """ {"_id": "5c9b6b722de0502ce0095985", "name": 1, "package": [{"name": "\u7eff\u7389\u5c60\u9f99", "act": 999, "p": "\u5e26\u6709\u6bd2\u7d20\u5c5e\u6027"}, {"name": "\u9ebb\u75f9\u6212\u6307", "act": 15, "p": "\u53ef\u8ba9\u5bf9\u65b9\u5904\u4e8e\u9ebb\u75f9\u72b6\u6001"}], "yuanbao": 99} """ from bson import ObjectId res = MONGO_DB.users.find_one({"_id":ObjectId("5c9b6b722de0502ce0095985")}) print(res) #根据ObjectId查询到指定宇宙唯一id的数据,前提是注意直通先通过bson 才能进行转换
...