flask6 MongoDB

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({})
# 可迭代对象 : <pymongo.cursor.Cursor object at 0x0000000002F17FD0>		
# 类似于生成器

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({}))
#可迭代对象 : <pymongo.cursor.Cursor object at 0x0000000002F17FD0>
# 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))     #<class 'list'>
print(res_json4,type(res_json4))    #  <class 'str'>
#{'_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)

 
posted @ 2019-07-17 12:30  learnacode  阅读(327)  评论(0编辑  收藏  举报