MongoDB修改与聚合二
1.修改方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
一 语法 里面有三个大的语句:一个是查询条件;一个是修改字段;一个是其他参数(目前就有两个) db.table.update( 条件, 修改字段, 其他参数 ) update db1.t1 set id=10 where name="egon";#这是sql语句的更新使用 db.table.update( {},#这是查询条件 {"age":11}, { "multi":true,#这是删除查询到的所有数据 "upsert":true#这是如果找不到这个数据,就新插入 } ) 1、update db1.user set age=23,name="武大郎" where name="wupeiqi"; #覆盖式更新就是替换掉查询到的数据,只能替换掉一个查询数据 db.user.update( {"name":"wupeiqi"}, {"age":23,"name":"武大郎"} ) #局部修改:$set就是只更改这里面显示的字段。 db.user.update( {"name":"alex"}, {"$set":{"age":73,"name":"潘金莲-alex"}} ) #改多条 db.user.update( {"_id":{"$gte":1,"$lte":2}}, {"$set":{"age":53,}}, {"multi":true} ) #有则修改,无则添加 db.user.update( {"name":"EGON"}, {"$set":{"name":"EGON","age":28,}}, { "multi":true, "upsert":true }#这个就是参数 ) #修改嵌套文档 db.user.update( {"name":"潘金莲-alex"}, {"$set":{"addr.country":"Japan"}}#如果需要查询到里面有嵌套的数据用.就可以查到。 ) #修改数组 db.user.update( {"name":"潘金莲-alex"}, {"$set":{"hobbies.1":"Piao"}}#如果需要查询到里面有嵌套的数据用.就可以查到。 ) #删除字段 db.user.update( {"name":"潘金莲-alex"}, {"$unset":{"hobbies":""}}#删除一个字段 ) 2、$inc db.user.update( {}, {"$inc":{"age":1}},#增加用的,如果是正数就说明是增加,如果是负数,就是减少 {"multi":true} ) db.user.update( {}, {"$inc":{"age":-10}}, {"multi":true} ) 3、$push, $pop $pull#对某个字段的添加或删除 db.user.update( {"name":"yuanhao"}, {"$push":{"hobbies":"tangtou"}},#对某一个字段是数组添加一个值 {"multi":true} ) db.user.update( {"name":"yuanhao"}, {"$push":{"hobbies":{"$each":["纹身","抽烟"]}}},#对某一个字段是数组添加多个值别忘了用$each {"multi":true} ) #从头删-1,从尾删1 db.user.update( {"name":"yuanhao"}, {"$pop":{"hobbies":-1}},#从开始删除 {"multi":true} ) db.user.update( {"name":"yuanhao"}, {"$pop":{"hobbies":1}},#从后面删除 {"multi":true} ) #按条件删 db.user.update( {"name":"yuanhao"}, {"$pull":{"hobbies":"纹身"}},#"$pull" 把符合条件的统统删掉,而$pop只能从两端删 {"multi":true} ) #3、$addToSet#添加数据,不重复添加 db.t3.insert({"urls":[]}) db.t3.update( {}, {"$addToSet":{"urls":{"$each":[ "http://www.baidu.com", "http://www.baidu.com", "http://www.baidu.com", "http://www.baidu.com", "http://www.baidu.com" ]}}}, {"multi":true} )
2.删除方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
db.user.deleteOne({"_id":{"$gte":3}})#在这种方法可以删除查询到的一个 db.user.deleteMany({"_id":{"$gte":3}})#这种方法可以删除查询到的所有值 db.user.deleteMany({})#删除所有的的数据
3.聚合方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
一:$match 例: select post from db1.emp where age > 20 group by post having avg(salary) > 10000;#把这个拆分3句话 #$match#查询的条件的标志 #1、select post from db1.emp where age > 20#sql db.emp.aggregate({"$match":{"age":{"$gt":20}}}) #aggregate是聚合的标志 #$group#分组 #2、select post from db1.emp where age > 20 group by post; db.emp.aggregate( {"$match":{"age":{"$gt":20}}}, {"$group":{"_id":"$post"}} ) #3、select post,avg(salary) as avg_salary from db1.emp where age > 20 group by post; db.emp.aggregate( {"$match":{"age":{"$gt":20}}}, {"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}}#这是显示的字段 #$salary是说明使用这个字段的值 ) #select post from db1.emp where age > 20 group by post having avg(salary) > 10000; db.emp.aggregate( {"$match":{"age":{"$gt":20}}}, {"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}}, {"$match":{"avg_salary":{"$gt":10000}}} ) 二:{"$project":{"要保留的字段名":1,"要去掉的字段名":0,"新增的字段名":"表达式"}}#映射是说明生成新的并展示新的表 例1: db.emp.aggregate( {"$project":{"_id":0,"name":1,"post":1,"annual_salary":{"$multiply":[12,"$salary"]}}}, {"$group":{"_id":"$post","平均年薪":{"$avg":"$annual_salary"}}}, {"$match":{"平均年薪":{"$gt":1000000}}}, {"$project":{"部门名":"$_id","平均年薪":1,"_id":0}} ) 例2:#$subtract是两个相减 db.emp.aggregate( {"$project":{"_id":0,"name":1,"hire_period":{"$subtract":[new Date(),"$hire_date"]}}} ) db.emp.aggregate( {"$project":{"_id":0,"name":1,"hire_year":{"$year":"$hire_date"}}}#取时间段的年 ) db.emp.aggregate( {"$project":{"_id":0,"name":1,"hire_period":{"$subtract":[{"$year":new Date()},{"$year":"$hire_date"}]}}}#工作了几年 ) 例3: db.emp.aggregate( {"$project":{"_id":0,"new_name":{"$toUpper":"$name"},}}#名字变成大写 ) db.emp.aggregate( {"$match":{"name":{"$ne":"egon"}}},#ne是比较运算里的 {"$project":{"_id":0,"new_name":{"$concat":["$name","_SB"]},}} ) db.emp.aggregate( {"$match":{"name":{"$ne":"egon"}}}, {"$project":{"_id":0,"new_name":{"$substr":["$name",0,3]},}}#$substr是截取某段 ) 三:{"$group":{"_id":分组字段,"新的字段名":聚合操作符}} #select post,max,min,sum,avg,count,group_concat from db1.emp group by post; db.emp.aggregate( {"$group":{ "_id":"$post", "max_age":{"$max":"$age"}, "min_id":{"$min":"$_id"},#$_id去找个字段的值 "avg_salary":{"$avg":"$salary"}, "sum_salary":{"$sum":"$salary"}, "count":{"$sum":1},#获取个数的用法 "names":{"$push":"$name"} } } ) 四:排序:$sort、限制:$limit、跳过:$skip db.emp.aggregate( {"$match":{"name":{"$ne":"egon"}}}, {"$project":{"_id":1,"new_name":{"$substr":["$name",0,3]},"age":1}}, {"$sort":{"age":1,"_id":-1}}, {"$skip":5}, {"$limit":5} ) # 补充 db.emp.aggregate({"$sample":{"size":3}})#随机去三个数
4.使用pymongo模块连接数据库
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from pymongo import MongoClient #pip3 install pymongo client=MongoClient("mongodb://root:123@127.0.0.1:27017")#连接数据库 # db1=client.db1 db1=client['db1'] # print(db1.collection_names()) # table_emp=db1.emp table_emp=db1['emp'] rows=table_emp.find({"_id":{"$gt":10}}) for row in rows: print(row)
爬虫提高方法的使用:
1.同步调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import requests #同步或者异步是指提交数据的方式 #同步是值原地等待提交任务返回结果 #异步是指一个任务提交完了,直接提交下一个任务。 def parse_page(res): print('PARSE %s' %(len(res))) def get_page(url): print('GET %s' %url) response=requests.get(url) if response.status_code == 200: return response.text if __name__ == '__main__': urls=[ 'https://www.baidu.com', 'https://www.taobao.com', 'https://www.openstack.org', ] for url in urls: res=get_page(url) parse_page(res)
2.多线程与多进程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import requests from threading import Thread,current_thread def parse_page(res): print('%s PARSE %s' %(current_thread().getName(),len(res))) def get_page(url,callback=parse_page): print('%s GET %s' %(current_thread().getName(),url)) response=requests.get(url) if response.status_code == 200: callback(response.text) if __name__ == '__main__': urls=[ 'https://www.baidu.com', 'https://www.taobao.com', 'https://www.openstack.org', ] for url in urls: t=Thread(target=get_page,args=(url,)) t.start()
3.线程池与进程池
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import requests from threading import current_thread#这个是打印出来现在是哪个线程。 from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor def parse_page(res): res=res.result() print('%s PARSE %s' %(current_thread().getName(),len(res))) def get_page(url): print('%s GET %s' %(current_thread().getName(),url)) response=requests.get(url) if response.status_code == 200: return response.text#返回的是字符串。 if __name__ == '__main__': urls=[ 'https://www.baidu.com', 'https://www.taobao.com', 'https://www.openstack.org', ] pool=ThreadPoolExecutor(50)#线程池 for url in urls: pool.submit(get_page,url).add_done_callback(parse_page) pool.shutdown(wait=True)#这个是不在往里面放任务。
4.协程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from gevent import joinall,spawn,monkey;monkey.patch_all()#协程 import requests from threading import current_thread def parse_page(res): print('%s PARSE %s' %(current_thread().getName(),len(res))) def get_page(url,callback=parse_page): print('%s GET %s' %(current_thread().getName(),url)) response=requests.get(url) if response.status_code == 200: callback(response.text) if __name__ == '__main__': urls=[ 'https://www.baidu.com', 'https://www.taobao.com', 'https://www.openstack.org', ] tasks=[] for url in urls: tasks.append(spawn(get_page,url)) joinall(tasks)
5.使用asyncio
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import requests import asyncio import uuid User_Agent='Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' def parse_page(res): with open('%s.html' %uuid.uuid1(),'wb') as f: f.write(res) @asyncio.coroutine def get_page(host,port=80,url='/',ssl=False,callback=parse_page): #1、建立连接 if ssl: port=443 print('下载:https:%s:%s:%s' %(host,port,url)) recv,send=yield from asyncio.open_connection(host=host,port=port,ssl=ssl) #2、封装请求头 request_headers="""GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n""" %(url,host,User_Agent) request_headers=request_headers.encode('utf-8') # socket发送的是bytes类型转成字节形式 #3、发送请求头 send.write(request_headers) yield from send.drain() #这是发送 #4、接收响应头 while True: line=yield from recv.readline() if line == b'\r\n': break print('%s 响应头: %s' %(host,line)) #5、接收响应体 text=yield from recv.read() # print(text) #6、执行回调函数完成解析 callback(text) #7、关闭 send.close() if __name__ == '__main__': tasks=[ get_page(host='www.baidu.com',url='/s?wd=美女',ssl=True), get_page(host='www.cnblogs.com',url='/linhaifeng/articles/7806303.html',ssl=True) ] loop=asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) loop.close()