MongoDB聚合查詢及Python連接MongoDB操作


今日內容概要

  • 聚合查詢

  • Python操作MongoDB

  • 第三方可視化視圖工具

今日內容詳細

  • 聚合查詢
  • Python操作MongoDB

數據准備

from pymongo import MongoClient # 載入pymongo模塊
import datetime # 載入datetime模塊
client = MongoClient('mongodb://root:666@localhost:27017')# 連接MongoDB數據庫(mongodb://用戶名:密碼@localhost(ip地址):port端口)
table = client['huangduoduo']['emp'] # client['數據庫']['所形成的的表名']
l=[
('egon','male','男',18,'20170301','teacher',7300.33,401,1),
('alex','male','男',78,'20150302','teacher',1000000.31,401,1),
('wupeiqi','male','男',81,'20130305','teacher',8300,401,1),
('yuanhao','male','男',73,'20140701','teacher',3500,401,1),
('liwenzhou','male',28,'20121101','teacher',2100,401,1),
('jingliyang','female',18,'20110211','teacher',9000,401,1),
('jinxin','male',18,'19000301','teacher',30000,401,1),
('成龍','male',48,'20101111','teacher',10000,401,1),
('歪歪','female',48,'20150311','sale',3000.13,402,2),
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),
('張野','male',28,'20160311','operation',10000.13,403,3), 
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬銀','female',18,'20130311','operation',19000,403,3),
('程咬銅','male',18,'20150411','operation',18000,403,3),
('程咬鐵','female',18,'20140512','operation',17000,403,3)
]
for n,item in enumerate(l):
    d={
        "_id":n,
        'name':item[0],
        'sex':item[1],
        'age':item[2],
        'hire_date':datetime.datetime.strptime(item[3],'%Y%m%d'),
        'post':item[4],
        'salary':item[5]
    }
    table.save(d)
    
# 以sql語句為例    
# 統計每個部門年齡大於20歲以上的員工的平均工資大於10000的部門和平均工資
select post,avg(salary) from emp where age>20 group by post having avg(salary)>10000;
'''在MongoDB中 設計到分組的 查詢關鍵字需要使用aggregate()'''
# 1.$match 篩選  等價於where和having
# select *from emp where age>20
db.emp.aggregate({'$match':{"age":{"$gt":20}}})

# 2.$group
# select post,avg(salary) from emp where age>20 group by post
db.emp.aggregate({'$match':{"age":{"$gt":20}}},{'$group':{"_id":"$post","avg_salary":{"$avg":"$salary"}}})
# _id是$group固定的用法不是主鍵_id,$post表示獲取鍵post對應的值
# 按什么分組就在鍵_id后面寫什么
'''
如果你想拿到鍵對應的值 很簡單
只需要在鍵的前面加上一個$符號就表示獲取鍵對應的值
$avg 等價於sql語句里面的聚合函數 avg()
'''
# 3.select post from 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}})
                                                                     '''
MySQL里面的關鍵字                                                           select
		from
		where
		group by
		having
		order by
		distinct
		limit
		regexp
                                                                     
MongoDB里面的關鍵字
		$each
		$match
		$group
		……
'''                                      

                                                                     # 投射(映射) $project
{"$project":{"要保留的字段名":1,"要去掉的字段名":0,"新增的字段名":"表達式"}} # 單純的映射意義不大  
 # select salary*12 from emp
# project還可以對數據做二次操作
db.emp.aggregate(
	{"$project":{"_id":0,"name":1,"post":1,"salary":1}}
)
# 只能拿固定的數據 無法直接操作
db.emp.find({},{"_id":0,"name":1,"post":1,"salary":1})


# 關鍵字$multiply對應的值放一個列表 會自動將列表中的多個元素相乘
  # 再分組取別的
      # 再篩選
          # 再次映射修改字段名
              
db.emp.aggregate(
	{"$project":{"_id":0,
               "name":1,
               "post":1,
               "annual_salary":{"$multiply":[12,"$salary"]}}},

  {"$group":{"_id":"$post","平均年薪":{"$avg":"$annual_salary"}}},

  {"$match":{"平均年薪":{"$gt":100000}}},
    {"$project":{"部門名":"$_id","平均年薪":1,"_id":0}}
)


#1、select name,post,(age+1) as new_age from db1.emp;
db.emp.aggregate(
    {"$project":{
        "name":1,
        "post":1,
        "年齡":{"$add":["$age",1]}
        }
})
"""
#2、表達式之數學表達式
{"$add":[expr1,expr2,...,exprN]} #相加
{"$subtract":[expr1,expr2]} #第一個減第二個
{"$multiply":[expr1,expr2,...,exprN]} #相乘
{"$divide":[expr1,expr2]} #第一個表達式除以第二個表達式的商作為結果
{"$mod":[expr1,expr2]} #第一個表達式除以第二個表達式得到的余數作為結果
"""

#例如:select name,date_format("%Y") as hire_year from emp
#3、表達式之日期表達式:$year,$month,$week,$dayOfMonth,$dayOfWeek,$dayOfYear,$hour,$minute,$second
db.emp.aggregate(
    {"$project":{"name":1,"hire_year":{"$year":"$hire_date"}}}
)


#例如查看每個員工的工作多長時間(年)
db.emp.aggregate(
    {"$project":{"name":1,"hire_period":{
        "$subtract":[
            {"$year":new Date()},
            {"$year":"$hire_date"}
        ]
    }}}
)

$group補充

#1、將分組字段傳給$group函數的_id字段即可
{"$group":{"_id":"$sex"}} #按照性別分組
{"$group":{"_id":"$post"}} #按照職位分組
{"$group":{"_id":{"state":"$state","city":"$city"}}} #按照多個字段分組,比如按照州市分組

#2、分組后聚合得結果,類似於sql中聚合函數的聚合操作符:$sum、$avg、$max、$min、$first、$last
#例1:select post,max(salary) from db1.emp group by post; 
db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"}}})

#例2:去每個部門最大薪資與最低薪資
db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}})

#例3:如果字段是排序后的,那么$first,$last會很有用,比用$max和$min效率高
db.emp.aggregate({"$group":{"_id":"$post","first_id":{"$first":"$_id"}}})

#例4:求每個部門的總工資
db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":"$salary"}}})

#例5:求每個部門的人數
db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":1}}})

#3、數組操作符
{"$addToSet":expr}:不重復
{"$push":expr}:重復

#例:查詢崗位名以及各崗位內的員工姓名:select post,group_concat(name) from db1.emp group by post;
db.emp.aggregate({"$group":{"_id":"$post","names":{"$push":"$name"}}})
db.emp.aggregate({"$group":{"_id":"$post","names":{"$addToSet":"$name"}}})

隨機獲取

#集合users包含的文檔如下
{ "_id" : 1, "name" : "dave123", "q1" : true, "q2" : true }
{ "_id" : 2, "name" : "dave2", "q1" : false, "q2" : false  }
{ "_id" : 3, "name" : "ahn", "q1" : true, "q2" : true  }
{ "_id" : 4, "name" : "li", "q1" : true, "q2" : false  }
{ "_id" : 5, "name" : "annT", "q1" : false, "q2" : true  }
{ "_id" : 6, "name" : "li", "q1" : true, "q2" : true  }
{ "_id" : 7, "name" : "ty", "q1" : false, "q2" : true  }

#下述操作時從users集合中隨機選取3個文檔
db.users.aggregate(
   [ { $sample: { size: 3 } } ]
)

可視化軟件

1.navicat里面也可以連接MongoDB
2.pycharm里面也可以連接
	jetbrains公司也專門開發了一款可以連接很多數據庫的軟件
3.robo 3.0T
	直接百度搜索下載即可

python代碼操作MongoDB

#用python操作mongodb
from pymongo import MongoClient

#1、鏈接
# client=MongoClient('mongodb://root:123@localhost:27017/')
client = MongoClient('localhost', 27017)

#2、use 數據庫
# db=client['db2'] #等同於:client.db1
db=client.test

#3、查看庫下所有的集合
# print(db.collection_names(include_system_collections=False))
#4、創建集合
table_user=db['table1'] #等同於:db.user
# table1=db.table1
# #5、插入文檔
# import datetime
# user0={
#     "_id":1,
#     "name":"egon",
#     "birth":datetime.datetime.now(),
#     "age":10,
#     'hobbies':['music','read','dancing'],
#     'addr':{
#         'country':'China',
#         'city':'BJ'
#     }
# }
#
# user1={
#     "_id":2,
#     "name":"alex",
#     "birth":datetime.datetime.now(),
#     "age":10,
#     'hobbies':['music','read','dancing'],
#     'addr':{
#         'country':'China',
#         'city':'weifang'
#     }
# }
# res=table_user.insert_many([user0,user1])
# print(res)
# print(table_user.count())

#6、查找

# from pprint import pprint#格式化細
# pprint(table_user.find_one())
# for item in table_user.find():
#     pprint(item)

print(table_user.find_one({"_id":{"$gte":1},"name":'egon'}))
table_user.find()

#7、更新
table_user.update({'_id':1},{'name':'EGON'})

#8、傳入新的文檔替換舊的文檔
table_user.save(
    {
        "_id":2,
        "name":'egon_xxx'
    }
)
作業
1. 查詢崗位名以及各崗位內的員工姓名
   db.emp.aggregate({"$group":{"_id":"$post","names":{"$addToSet":"$name"}}})
2. 查詢崗位名以及各崗位內包含的員工個數
   db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":1}}})
3. 查詢公司內男員工和女員工的個數
   db.emp.aggregat({"$group":{"_id":"$sex","count":{"$sum":1}}})
4. 查詢崗位名以及各崗位的平均薪資、最高薪資、最低薪資
   db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}})
5. 查詢男員工與男員工的平均薪資,女員工與女員工的平均薪資
  db.emp.aggregat({"$group":{"_id":"$sex","avg_salary":{"$avg":"$salary"}}})
6. 查詢各崗位內包含的員工個數小於2的崗位名、崗位內包含員工名字、個數
db.emp.aggregate({"$group":{"_id":"$post","names":{"$addToSet":"$name"},"count":{"$sum":1}},
                      "$match":{"count":{"$lt":2}},
                      "$project":{"_id":0,"names":1,"count":1}})
7. 查詢各崗位平均薪資大於10000的崗位名、平均工資
 db.emp.aggregate({"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}},
                       "$match":{"avg_salary":{"$gt":10000}}})
8. 查詢各崗位平均薪資大於10000且小於20000的崗位名、平均工資
 db.emp.aggregate({"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}},
                       "$match":{"avg_salary":{"$gt":10000,"$lt":20000}}})
9. 查詢所有員工信息,先按照age升序排序,如果age相同則按照hire_date降序排序
db.emp.aggregate({"$sort":{"age":1,"hire_date":-1}})
10. 查詢各崗位平均薪資大於10000的崗位名、平均工資,結果按平均薪資升序排列
db.emp.aggregate({"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}},
                      "$match":{"avg_salary":{"$gt":10000}},
                      "$sort":{"avg_salary":1}})
11. 查詢各崗位平均薪資大於10000的崗位名、平均工資,結果按平均薪資降序排列,取前1個
db.emp.aggregate({"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}},
                      "$match":{"avg_salary":{"$gt":10000}},
                      "$sort":{"avg_salary":-1},"$limit":1})


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM