flask6 MongoDB
一.背景
nosqll - MongoDB 文件型数据库
文件型 - MongoDB
User:
[
{id:1,name:'蔡文姬',age:16,gender:'女'},
{id:2,name:'嫦娥',age:16,gender:'女'},
{id:3,name:'西施',age:16,gender:'女'},
]
关系型(拉里艾莉森) - MySQL MSSQL(SQLServer微软,Windows) Sybase ORACLE(MySQL被收编)(虽然是免费的,有问题,付费) DB2+AUX(IBM)
1 . 把精力放在重要的逻辑上,细节,记住他怎么用就行! 会了逻辑,才有信心往后看。
士别三日当刮目相待-吴下阿蒙
2 . 不要等,主动去找事情做。
MySQL MS - MySQL Ux
User:
建表 ID (int 自增 主键) name age gender
ID
name
age
gender
1
蔡文姬
16
女
2
嫦娥
333
女
为什么开发 MongoDB呢,关系型的不好吗?
之前的服务器级别的空间是20G,硬盘是8G,空间很小。内存8M。
缺点:查找速度不快(之前,现在告诉硬盘14400转快了),占用空间还非常大。
优点:
主要是数据格式是JSON,方便传输。
而且操作简单方便移动更加接近程序员操作(打点操作)原生语法 ORM
因为非关系型数据库,没有结构限制(),扩展性极强
[{id:1,name:'蔡文姬',age:16,gender:'女'},
{id:四(不受限),name:123,age:‘十六’,gender:1,hobby:[2,3,4]},]
mysql的话,有限制
MongoDB数据越多,存储数据比别的数据库,占用的空间越高 ? (数据少的时候差不多)
1.安装MongoDB
只卖服务不卖数据库
4版本比3版本多了个事务,还做得不是很好
程序员读懂:exception: connect failed
连接成功的话,cmd窗口会夯住
三个数据库默认端口
MongoDB port=27017
MYSQL 3306
Redis 6379
29 Data directory C:\data\db\ not found., terminating
新建C:\data\db\ 可以的,但是200m太大了,查看帮助,新建到d盘,加到路径下
--dbpath arg directory for datafiles - defaults to
\data\db\ which is C:\data\db\ based on
the current working drive
CMD-
dbpath 数据库存在路径(必须存在)
mongod --dbpath D:\MongoDB\data\db
2 . 基本操作命令
db -- 当前使用的数据库 查看名称,代指当前使用的数据库show databases 查看当前的数据库
use dbname 切换当前使用的数据库 或者在内存中创建一个新的数据库 赋值给db
show tables 查看当前服务器磁盘上的所有数据库
db.tablename -- 使用当前数据库中的tablename 在内存中创建表 (没有就创建,有就用了)
use locall 没有也可已进去
db.user.insert({name:'Alexander'}) show databases 就有了数据库和表
MongoDB的特性 : 使用不存在的对象即创建该对象 (类似于python中的_setattr_)
3 增删改查
增
db.tabelname.insert({name:'123'})#在硬盘中写入数据{name:'123'}
db.tabelname.insert([{name:'123'},{name:'123'}])
查
db.tabelname.find({查询条件})
db.tabelname.find({name:'458'})#查询符合条件的所有数据
db.stu.find({'_id':ObjectId("5d2e8f8c4e27500eac420266")})
改
db.tabelname.update({查询条件},{$修改器:{修改属性}})
根据查询条件,修改第一条符合条件的值
#修改器:认定当前修改的类型 $set设置类型修改器 强制修改某字段的值
db.tabelname.update({{name:'458'}},{$set:{修改属性}})
db.tabelname.update({name:'458'},{$set:{name:789}})
# 双精度的
db.tabelname.update({name:'458'},{$set:{name:789}},{multi:true}) #全修改 (不提倡的写法,带参数)
删
db.tabelname.remove({查询条件}) #删除所有符合条件的字段
db.tabelname.remove({}) #删除所有的表
db.tabelname.drop()#删除整个表
删库 db.dropDatabase()
结果
> db.tabelname.insert({name:'123'},{name:'123'})
WriteResult({ "nInserted" : 1 })
> db.tabelname.insert([{name:'123'},{name:'123'}])
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
> db.tabelname.find({name:'458'})
{ "_id" : ObjectId("5d2e88cb8b6adeb6be07d5fb"), "name" : "458" }#对象id
如果已安装pip,执行pip install baidu-aip即可。
4. MongoDB 数据类型
ObjectID :Documents 自生成的 _id
String: 字符串,必须是utf-8
Boolean:布尔值,true 或者false (这里有坑哦~在我们大Python中 True False 首字母大写)
Integer:整数 (Int32 Int64 你们就知道有个Int就行了,一般我们用Int32)
Double:浮点数 (没有float类型,所有小数都是Double).前后16位
Arrays:数组或者列表,多个值存储到一个键 (list哦,大Python中的List哦)
Object:如果你学过Python的话,那么这个概念特别好理解,就是Python中的字典,这个数据类型就是字典
Null:空数据类型 , 一个特殊的概念,None Null
Timestamp:时间戳
Date:存储当前日期或时间unix时间格式 (我们一般不用这个Date类型,时间戳可以秒杀一切时间类型)
MYSQL
MongoDB
口语
database
database
数据库
tables
Collections
表
column
Field
列
row
Document
数据 - 一条数据
"_id" : ObjectId("5b151f8536409809ab2e6b26")
#"5b151f85" 代指的是时间戳,这条数据的产生时间(一直在变)
#"364098" 代指某台机器的机器码,存储这条数据时的机器编号
#"09ab" 代指进程ID,多进程存储数据的时候,非常有用的
#"2e6b26" 代指计数器,这里要注意的是,计数器的数字可能会出现重复,不是唯一的(是针对所有的表的)
#以上四种标识符拼凑成世界上唯一的ObjectID
#只要是支持MongoDB的语言,都会有一个或多个方法,对ObjectID进行转换
#可以得到以上四种信息
#注意:这个类型是不可以被JSON序列化的
object 嵌套3级就好,套的再多了 就很慢
5 数学比较符
db.stu.find({age:{$lt:10}})
$lt 小于
$lte 小于等于
$gt 大于
$gte 于等于
$eq : 等于 (:不起作用时)
$ne 不等于
db.stu.find({age:{$lt:10}})#并列条件查询
6 $ 修改器+ $字符特殊用法
MongoDB中的那些个update修改器: $inc $set $unset $push $pull
$set 修改某个字段的值
$unset 删除字段的值 db.stu.update({name:'self'},{$unset:{mytime:1}},)
$inc 引用增加 先引用 后增加
db.stu.update({},{$inc:{age:1}})#update只第一个人 +1
db.stu.update({},{$inc:{age:-1}})#年龄加 -1
针对Array == list操作
$push == append()
$pushAll == extend()
$pull == remove()
$pop (=) pop()
#在Array的最后一个位置增加数据
db.stu.update({name:'小黑'},{$push:{hobbys:'站南'}} )
#在删除Array中的指定元素
db.stu.update({name:'小黑'},{$pull:{hobbys:'站南'}} )
#删除Array的第一个或者最后一个元素,正数是倒序删除 负数是正序删除
db.stu.update({name:'小黑'},{$pop:{hobbys:1}} )
# 删除多个
db.stu.update({name:'小白'},
{$pullAll:{hobbys:[1,2,3,4,5]}},
)
hobby.$'符合前面的值的下标位置
db.stu.update({'hobby':'5'},{$set:{'hobby.4':'五'}})#4是下标,这是已知的,不知道的呢? 看下面---->
db.stu.update({'hobby':'5'},{$set:{'hobby.$':'五'}})
7.object 操作
首先要有这个表 (用.取属性)
db.stu.update({name:'小黑'},{$set:{'hobby.抽烟':'1包'}})
object 还是 Aerry 有.属性
db.stu.update({name:'小白','package.name':'绝世好剑'},{$inc:{'package.$.count':-1}})
Array+Object
$字符特殊用法
$ 字符特殊用法
存储当前(Array)符合条件的元素下标索引 ,只能存储最外层的 索引位置
例子:hobbys中等于5的元素改为 "五"
先查询到hobbys中5的 位置(2) ,将位置存储在 $==(2) 字符中 然后根据$字符的位置(2)更改数据
db.stu.update({"hoobys":5},{ $set: {"hoobys.$":"五"} })
上午的MongoDB语法
db.stu.find({'_id':ObjectId("5d2e8f8c4e27500eac420266")})
db.stu.insert(//添加多个
[
{name:'小白',age:13},
{name:'小bao',age:13},
{name:'小re',age:17},
)
db.stu.find({age:{$lt:16}})//查看小于16的年龄
db.stu.update({age:13}, //改多个属性
{$set:{name:'屡屡',gender:1}},
)
db.stu.find({age:20,gender:1})//多条件查询
db.stu.update({name:'self'},{$unset:{mytime:1}},) //删除
db.stu.update({},{$inc:{age:1}})//增加年龄
db.stu.find({name:'小黑'})//
db.stu.update({name:'小黑'},{$push:{hobbys:'站南'}} )//增加
db.stu.update({name:'小黑'},{$pull:{hobbys:'站南'}} )//删除
db.stu.update({name:'小黑'},{$pop:{hobbys:0}} ) //删除
db.stu.remove({})
db.stu.find({name:'小白'})
db.stu.insert([{name:'小白',age:[1,2,3,4,'5']}])
db.stu.update({'age':'5'},{$set:{'age.$':'五'}})//$用法
db.stu.find({name:'小白'})
db.stu.update({name:'小白'},{$set:{'hobby.抽烟':'1包'}}) //.的用法
db.stu.update({name:'小白','package.name':'绝世好剑'},{$inc:{'package.$.count':-1}})//增加属性
db.stu.update({name:'小白','package.name':'绝世好剑'},{$inc:{'package.$.count':-1}})
db.stu.update({name:'小白'}, //删除所有
{$pullAll:{hobbys:[1,2,3,4,5]}},
)
查询关键字
并列查询
and
条件查询
or
子集查询
all
范围查询
in
and
db.stu.find({age:20,gender:1})
db.stu.find({$and:[{name:'小白'},{age:13}]})#位置一样顺序不一样 ,还可以加and
or
db.stu.find({$or:[{name:'白'},{age:13}]})
all
db.stu.find({'age':{$all:[1,2,3,4]}}) #全都在里面才可以
in
db.stu.find({name:{$in :['屡屡','小白','蓝蓝']}})
8 . 官方给出的推荐增删改查版本
新版3.2之后
增
官方不推荐使用insert了
db.stu.insertOne({name:'6666'})#只能插入字典
db.stu.insertMany([{name:777},{name:888}])
增加数据的_id ObjectId
增加数据的_id ObjectId 列表 [objectId,objectId]
insertedId: ObjectId("5d2ecd2a4e27500eac420287")
"insertedIds" : [
ObjectId("5d2ecd594e27500eac420288"),
ObjectId("5d2ecd594e27500eac420289")
]
查
db.tablename.findOne({查询条件}) #返回json数据(不似转)
改
db.tabelname.updateOne({{name:'458'}},{'$set':{修改属性}})
db.tabelname.updateMany({{name:'458'}},{'$set':{修改属性}})#修改符合条件的所有数据
删
官方不推荐使用remove了
3.2
db.tablename.deleteOne()
db.tablename.deleteMany()
9 . 排序 + 选取 + 跳过
排序:db.stu.find().sort({age:-1}) 1 正序 -1 倒叙
选取:db.stu.find().limit(2) 选取两条数据
跳过:db.stu.find().skip(2) 跳过前两条数据
中间两条 or 跳过前N条
db.stu.find().sort({age:-1}).skip(2).limit(2) #分页
先排序 - 后跳过 - 选取 #limit最后那个 默认的
var page = 1
var num = 2
var sk = (page-1)*num
db.stu.find().sort({age:-1}).skip(sk).limit(num)
10 . python操作MongoDB
mysql 做不到,一列列的,MongoDB是字典的,好操作
pop 本来就是从后往前删,所以1,正序,就是从后往前,-1就是从前往后
作业:今天晚上+明天上午
错误 1
user = mdb.user.find_one({{'name':'A_C'}})
TypeError: unhashable type: 'dict'
user = mdb.user.find_one({'name':'A_C'})
多加了个括号 , 错误:{{}} {} ~= get({})
错误 ; [] 是因为查错了表,那个表里没有那个内容的
list 可以显示出所有的表里的内容,如果没有,应该是自己没写别的内容 已经有2个,就不止是一个的。很多应该可以
存下mongDB的值
python操作 MongoDB
from bson import ObjectId
from pymongo import MongoClient
from pymongo.cursor import Cursor# 查看Cursor
import json
#建立连接
m_client = MongoClient('127.0.0.1',27017)
#MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True)
#连接数据库
mdb = m_client['s20']
#Database(MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True), 's20')
# 建立一个表
res = mdb.user.insert_one({'name':'liuyang'})
res.inserted_id #5d2eee8fa456512a54ad1d07
res1 = mdb.user.insert_many([{'name':'小黑'},{'name':'xiaobai'}])
错误:
res1.inserted_id #AttributeError: 'InsertManyResult' object has no attribute 'inserted_id'
正确:
res1.inserted_ids #[ObjectId('5d2eef580f9d91164701f179'), ObjectId('5d2eef580f9d91164701f17a')]
#增加数据时 inserted_id 和 inserted_ids 都是 ObjectId 不是字符串
#显示的是字符串,其实是onbjectid
# 查:
res2 = mdb.user.find({})
# 可迭代对象 :
# 类似于生成器
res2_list = list(res2)
# [{'_id': ObjectId('5d2eee8fa456512a54ad1d07'), 'name': 'liuyang'}, {'_id':
for user in res2_list:
print(user)
# {'_id': ObjectId('5d2eef37e08e63aaa00b3a29'), 'name': '小黑'}
# {'_id': ObjectId('5d2eef37e08e63aaa00b3a2a'), 'name': 'xiaobai'}
res3 = mdb.user.find_one({}) # find_one 是个字典啊
print(res3,res3.get('_id')) # {'_id': ObjectId('5d2eee8fa456512a54ad1d07'), 'name': 'liuyang'} 5d2eee8fa456512a54ad1d07 显示的是字符串,实际上是objectid
res4 = mdb.user.find_one({'_id': ObjectId('5d2eee8fa456512a54ad1d07')})
#{'_id': ObjectId('5d2eee8fa456512a54ad1d07'), 'name': 'liuyang'}
# 转成json化,方便传输
res_json = json.dumps(str(res4))
# 列表可以被json, 但是这个列表中包含着字典 每一个字典都不行
# TypeError: Object of type 'ObjectId' is not JSON serializable # 是int型的因
# "{'_id': ObjectId('5d2eee8fa456512a54ad1d07'), 'name': 'liuyang'}"
# 错误 : 虽然类别可以,但是类别里面有不能的字典的int型 得转换了
# res2 = list(mdb.user.find({}))
#可迭代对象 :
# res_json2 = json.dumps(res2)
# TypeError: Object of type 'ObjectId' is not JSON serializable
# 大体思路
# res['_id'] = str(res.get('_id'))
#变成字符串 才可以被json化 flask的jsonfiy也不可以
# print(res,str(res.get('_id')))
# res_json = json.dumps(res)
# print(res_json)
#用for循环,基于老师下面 的改
res2 = list(mdb.user.find({}))
for user in res2:
user['_id'] = str(user['_id'])
res_json4 = json.dumps(res2)
print(res2, type(res2)) #
print(res_json4,type(res_json4)) #
#{'_id': '5d2eef2c00e7ac7934ce1391', 'name': 'liuyang'}, {'_id': '5d2eef2c00e7ac7934ce1392', 'name': '小黑'}
# {"_id": "5d2eef2c00e7ac7934ce1391", "name": "liuyang"}, {"_id": "5d2eef2c00e7ac7934ce1392", "name": "\u5c0f\u9ed1"}
# 数据对比之下, 怎么 name变成了 二进制 json.dumps()
# json.dumps输出 汉字
res_jsonhanzi = json.dumps(res2,ensure_ascii=False)
print(res2)
print(res_jsonhanzi)
# ASCII 编码是最简单的西文编码方案 non-ASCII
'''
If ``ensure_ascii`` is false, then the return value can contain non-ASCII
characters if they appear in strings contained in ``obj``. Otherwise, all
such characters are escaped in JSON strings.'''
# 用for循环
# res_list = []
# for user in res:
# user['_id'] = str(user.get('_id'))
# res_list.append(user)
# res_json3 = json.dumps(res_list)
# print(res_json3)
'''
# 列表的空间节省方法的
res222 = list(mdb.user.find({}))
for index,user in enumerate(res222):
res222[index]['_id'] = set(user.get('_id'))
print(json.dumps(res222))
'''
# 修改数据
res5 = mdb.user.update_one({'name': 'liuyang'}, {'$set':{'name':'A_C'}})
# The number of documents modified.
print(res5, dir(res5))
print(res5.modified_count) #xx.modified_count 删除和修改的时候都有 1
print(list(mdb.user.find()))
user = mdb.user.find_one({'name':'A_C'})
print('user:',user)
user['gender'] = 1
user['name'] = 1
user['hobby'] = 1
print('user:',user)
res6 = mdb.user.update_one({"name":'A_C'},{'$set':user})
print(res6 ,dir(res6) )
print(list(mdb.user.find({'name':'A_C'}))) # 显示的知识id和name没有别的了吗
showAll = mdb.user.find({'name':'A_C'})
print(dir(showAll)) # 都是cursor的
info_xiaobai = mdb.stu.find({'name':'小白'})
print(list(info_xiaobai))
# and or all 什么的太麻烦 改了塞进去
# [{'_id': ObjectId('5d2ed07f4e27500eac420290'), 'name': '小白', 'age': [1.0, 2.0, 3.0, 4.0, '五'], 'hobby': {'抽烟': '1包'}}]
# 有两个小白,导致操作不对,结果 删了一个
# mdb.stu.delete_one({'name':'小白'})
user2 = mdb.stu.find_one({'name':'小白'}) # 错误原因 用了find 找了一个字典
user2['hobby'] = ['抽烟','喝酒','烫头'] # 改了知识盖的字典的,还没有改到数据库中
# user2['hobby'].remove('抽烟')
# print(user2['hobby'])
# print(list(user2))
# [{'_id': ObjectId('5d2ed0 '), 'name': '小白', 五'], 'hobby': ['喝酒', '烫头'], '抽烟': '1包'}] # 这个 '抽烟'是字典吗
mdb.stu.update_one({'name':'小白'},{'$set':{'hobby':user2['hobby']}}) #是添加的
print(list(mdb.stu.find_one({'name':'小白'})))
print(user2)
# 删除
# res = mdb.user.delete_one({})
# print(res.deleted_count) #1
# 删除某个字段 unset 和 字典pop都行
# 排序 + skip + limit
res = list(mdb.stu.find())
print(res)
import pymongo
res1 = mdb.stu.find().sort('age',pymongo.ASCENDING) # ASCENDING = 1
# """Ascending sort order.""" 正序
for s in res1:
print(s)
res2 = list(mdb.stu.find().skip(2))
# 分页
res3 = list(mdb.stu.find().sort('age',pymongo.ASCENDING).limit(2).skip(2))
print('排序')
print(res1,'\n',res2,'\n',res3)