Python|Python互動之mongoDB互動詳解

技術小能手發表於2018-08-28

前言
本篇為mongodb篇,包含例項演示,mongodb高階查詢,mongodb聚合管道,python互動等內容。

mongoDB的優勢
易擴充套件

大資料量,高效能

靈活的資料模型

安裝與啟動

安裝mongodb:sudo apt-get install -y mongodb-org
安裝視覺化管理介面:https://robomongo.org/download

檢視幫助:mongod –help
啟動服務:sudo service mongod start
停止服務:sudo service mongod stop
重啟服務:sudo service mongod restart
檢視程式:ps ajx|grep mongod

配置檔案的位置:/etc/mongod.conf
預設埠:27017
日誌的位置:/var/log/mongodb/mongod.log
mongodb資料庫操作
資料庫操作
檢視當前的資料庫:db
檢視所有的資料庫:show dbs  /show databases
切換資料庫:use db_name
刪除當前的資料庫:db.dropDatabase()

集合操作

當集合不存在時,插入任何一條資料集合自動建立。
或者手動建立集合:db.createCollection(name,[options])
其中options:

引數capped: 預設值為false表示不設定上限,值為true表示設定上限

引數size: 當capped值為true時,需要指定此引數,表示上限大小,當文件達到上限時,會將之前的資料覆蓋,單位為位元組
當集合存在時:
檢視集合:show collections
刪除集合:db.集合名稱.drop()
mongodb資料型別
Object ID:文件ID

String: 字串,最常使用,必須是有效的UTF-8

Boolean: 儲存一個布林值,true或false

Integer: 整數可以是32位或64位,這取決於伺服器

Double: 儲存浮點值

Arrays: 陣列或列表, 多個值儲存到一個鍵

Object: 用於嵌入式的文件, 即一個值為一個文件

Null: 儲存Null值

Timestamp: 時間戳,表示從1970-1-1到現在的總秒數

Date: 儲存當前日期或時間的UNIX時間格式

注意點:

建立日期語句如下 :引數的格式為YYYY-MM-DD
                new Date(`2017-12-20`)

每個文件都有一個屬性,為_id,保證每個文件的唯一性
可以自己去設定_id插入文件,如果沒有提供,那麼MongoDB為每個⽂檔提供了一個獨特的_id,型別為objectID

objectID是一個12位元組的十六進位制數:
前4個位元組為當前時間戳
接下來3個位元組的機器ID
接下來的2個位元組中MongoDB的服務程式id
最後3個位元組是簡單的增量值
mongodb資料操作
新增
插入資料(欄位_id存在就報錯):db.集合名稱.insert(document)

插入資料(欄位_id存在就更新):db.集合名稱.save(document)

舉個例子:

#插入文件時,如果不指定_id引數,MongoDB會為文件分配一個唯一的ObjectId
db.xianyu.insert({name:"xianyuplus",age:"3"})

#插入文件時,可以指定_id引數
db.xianyu.insert({_id:"10001",name:"xianyuplus",age:"30"})

#更新了上面_id為1001的文件
db.xianyu.save({_id:"10001",name:"xianyuplus",age:"40"})
查詢
查詢資料:db.集合名稱.find()

舉個例子:

db.xianyu.find()
更新
更新資料:db.集合名稱.update(<query> ,<update>,{multi: <boolean>})

引數query:查詢條件

引數update:更新操作符

引數multi:可選,預設是false,表示只更新找到的第一條記錄,值為true表示把滿足條件的文件全部更新
舉個例子:

原有內容:

{
    "_id" : ObjectId("5b66f05f1194e110103bc283"),
    "name": "xianyuplus",
    "age": "40"
    }

# 將name為xianyuplus的值替換為xianyuplus1
db.xianyu.update({name:"xianyuplus"},{name:"xianyuplus1"})

操作後內容:

{
    "_id" : ObjectId("5b66f05f1194e110103bc283"),
    "name": "xianyuplus1"
    }

可以看到單單使用update更新資料會導致原有資料被新資料替換,所以我們應該搭配$set使用,指定更新對應的鍵值。

舉個例子:

原有內容:
{
    "_id" : ObjectId("5b66f05f1194e110103bc283"),
    "name": "xianyuplus",
    "age": "40"
    }
# 將name為xianyuplus的值更新為xianyuplus1
db.xianyu.update({name:"xianyuplus"},{$set:{name:"xianyuplus1"}})

操作後內容:
{
    "_id" : ObjectId("5b66f05f1194e110103bc283"),
    "name": "xianyuplus1",
    "age": "40"
    }
更新多條資料:使用引數multi:true

舉個例子:

# 更新全部資料的name值為xianyuplus1
db.stu.update({},{$set:{name:"xianyuplus1"}},{multi:true})
注意:multi update only works with $ operators 即multi只要和$搭配使用時才能起效。

刪除
刪除資料:db.集合名稱.remove(,{justOne: })

引數query:可選,刪除的文件的條件

引數justOne:可選,如果設為true或1,則只刪除一條,預設fals,表示刪除多條
舉個例子:

# 把name值為xianyuplus的資料全部刪掉
db.xianyu.remove({name:"xianyuplus"})
mongodb高階查詢
mongodb查詢方法
查詢文件:db.集合名稱.find({條件文件})
查詢一條資料:db.集合名稱.findOne({條件文件})
格式化查詢:db.集合名稱.find({條件文件}).pretty()

舉個例子:

# 查詢name為xianyuplus的資料
db.xianyu.find({name:"xianyuplus"})

# 查詢一條name為xianyuplus的資料
db.xianyu.findOne({name:"xianyuplus"})
mongodb的比較運算子
等於:如上述栗子
大於:$gt ( greater than )
大於等於:$gte ( greater than equal )
小於:$lt ( less than )
小於等於:$lte ( less than equal )
不等於:$nt ( not equal )

舉個例子:

# 查詢age大於20的資料
db.xianyu.find({age:{$gt:20}})

# 查詢age大於等於20的資料
db.xianyu.find({age:{$gte:20}})

# 查詢age小於20的資料
db.xianyu.find({age:{$lt:20}})

# 查詢age小於等於20的資料
db.xianyu.find({age:{$lte:20}})

# 查詢age不等於20的資料
db.xianyu.find({age:{$ne:20}})
mongodb邏輯運算子
and:在find條件文件中寫入多個欄位條件即可
or:使用$or

舉個例子:

#查詢name為xianyuplus且age為20的資料
db.xianyu.find({name:"xianyuplus",age:20})

#查詢name為xianyuplus或age為20的資料
db.xianyu.find({$or:[{name:"xianyuplus"},{age:20}]})

#查詢name為xianyuplus或age大於20的資料
db.xianyu.find({$or:[{age:{$gt:20}},{name:"xianyuplus"}]})

#查詢age大於等於20或gender為男並且name為xianyuplus的資料
db.xianyu.find({$or:[{gender:"true"},{age:{$gte:18}}],name:"xianyuplus"})
mongodb範圍運算子
使用$in與$nin判斷是否在某一範圍內

舉個例子:

#查詢年齡為18、28的資料
db.xianyu.find({age:{$in:[]18,28}})
mongodb使用正規表示式
使用//或$regex編寫正規表示式

舉個例子:

# 查詢name以xian開頭的資料
db.xianyu.find({name:/^xianyu/})
db.xianyu.find({name:{$regex:`^xianyu`}})
mongodb分頁與跳過
查詢前n條資料:db.集合名稱.find().limit(NUMBER)

跳過n條資料:db.集合名稱.find().skip(NUMBER)

舉個例子:

#查詢前3條資料
db.xianyu.find().limit(3)

#查詢3條後的資料
db.xianyu.find().skip(3)

#skip和limit可以搭配使用,查詢4,5,6條資料
db.xianyu.find().skip(3).limit(3)
mongodb自定義查詢

使用$where自定義查詢,這裡使用的是js語法

舉個例子:

//查詢age大於30的資料
db.xianyu.find({
    $where:function() {
        return this.age>30;}
})

mongodb投影
投影:在查詢結果中只顯示你想要看到的資料欄位內容。

db.集合名稱.find({},{欄位名稱:1,...})

想顯示的欄位設定為1,不想顯示的欄位不設定,而_id這個欄位比較特殊,想要他不顯示需要設定_id為0。

#查詢結果中只顯示name欄位,不顯示age
db.xianyu.find({},{name:1})
mongodb排序
排序:db.集合名稱.find().sort({欄位:1,...})

將需要排序的欄位設定值:升序為1,降序為-1

舉個例子:

#先按照性別降序排列再按照年齡升序排列
db.xianyu.find().sort({gender:-1,age:1})
mongodb計數
統計數目:db.集合名稱.find({條件}).count()
db.集合名稱.count({條件})

舉個例子:

#查詢age為20的資料個數
db.xianyu.find({age:20}).count()
#查詢age大於20,且性別為nan的資料個數
db.xianyu.count({age:{$gt:20},gender:true})
mongodb去重
去重:db.集合名稱.distinct(`去重欄位`,{條件})

舉個例子:

#去除家鄉相同,且年齡大於18的資料
db.xianyu.distinct(`hometown`,{age:{$gt:18}})
mongodb管道與聚合

聚合(aggregate)是基於資料處理的聚合管道,每個文件通過一個由多個階段(stage)組成的管道,可以對每個階段的管道進行分組、過濾等功能,然後經過一系列的處理,輸出相應的結果。

用法:db.集合名稱.aggregate({管道:{表示式}})

常用管道:

$group: 將集合中的文件分組, 可用於統計結果
$match: 過濾資料, 只輸出符合條件的文件
$project: 修改輸出文件的結構, 如重新命名、 增加、 刪除欄位、 建立計算結果
$sort: 將輸出文件排序後輸出
$limit: 限制聚合管道返回的文件數
$skip: 跳過指定數量的文件, 並返回餘下的文件
$unwind: 將陣列型別的欄位進行拆分
常用表示式:表示式:"列名"

$sum: 計算總和, $sum:1 表示以一倍計數
$avg: 計算平均值
$min: 獲取最小值
$max: 獲取最大值
$push: 在結果文件中插入值到一個陣列中
$first: 根據資源文件的排序獲取第一個文件資料
$last: 根據資源文件的排序獲取最後一個文件資料
聚合之$group
group:將文件進行分組以便於統計數目

用法:_id表示分組依據,_id:”$欄位名”

舉個例子:

#按照hometown分組,並計數
db.xianyu.aggregate({$group:{_id:"$hometown", count:{$sum:1}}})

#將集合中所有的內容分為一組,統計個數
db.xianyu.aggregate({$group:{_id:null, count:{$sum:1}}})
聚合之$project
project:修改輸入文件的結構,如:重新命名,增加、刪除欄位等

舉個例子:

#按照hometown分組,並計數
#分組輸出,只顯示count欄位
 db.xianyu.aggregate(
        {$group:{_id:"$hometown", count:{$sum:1}}},
        {$project:{_id:0,count:1}}
 )

聚合之$match
match:用於過濾資料,只輸出符合條件的文件,功能和find類似,但是match是管道命令,能將結果交給後一個管道,但是find不可以。

舉個例子:

#查詢age大於20
#按照hometown分組,並計數
#分組輸出,只顯示count欄位
 db.xianyu.aggregate(
        {$match:{age:{$gte:20}}},
        {$group:{_id:"$hometown", count:{$sum:1}}},
        {$project:{_id:0,count:1}}
 )
聚合之$sort
sort:將輸入文件排序後輸出

舉個例子:

#查詢age大於20
#按照hometown分組,並計數
#分組輸出,只顯示count欄位
#按照計數升序排序
 db.xianyu.aggregate(
        {$match:{age:{$gte:20}}},
        {$group:{_id:"$hometown", count:{$sum:1}}},
        {$project:{_id:0,count:1}},
        {$sort:{count:1}}
 )
聚合之$limit與$skip

limit:限制聚合管道返回的文件數

skip:跳過指定數量的文件數,返回剩下的文件

舉個例子:

#查詢age大於20
#按照hometown分組,並計數
#按照計數升序排序
#跳過前一個文件,返回第二個
 db.xianyu.aggregate(
        {$match:{age:{$gte:20}}},
        {$group:{_id:"$hometown", count:{$sum:1}}},
        {$sort:{count:1}},
        {$skip:1},
        {$limit:1}
 )

聚合之$unwind
unwind:將文件中的某一個陣列型別欄位拆分成多條, 每條包含陣列中的一個值

db.集合名稱.aggregate({$unwind:`$欄位名稱`})

舉個例子:

db.xianyu.insert({_id:1,item:`t-shirt`,size:[`S`,`M`,`L`]})
db.xianyu.aggregate({$unwind:`$size`})
輸出:
{ "_id" : 1, "item" : "t-shirt", "size" : "S" }
{ "_id" : 1, "item" : "t-shirt", "size" : "M" }
{ "_id" : 1, "item" : "t-shirt", "size" : "L" }

聚合使用注意事項
$group對應的字典中有幾個鍵,結果中就有幾個鍵

分組依據需要放到_id後面

取不同的欄位的值需要使用$,$gender,$age

取字典巢狀的字典中的值的時候$_id.country

能夠同時按照多個鍵進行分組
{$group:{_id:{country:”$欄位”,province:”$欄位”}}}

mongodb索引
用法:db.集合.ensureIndex({屬性:1}),1表示升序, -1表示降序

建立唯一索引:db.集合.ensureIndex({“屬性”:1},{“unique”:true})
建立唯一索引並消除:
db.集合.ensureIndex({“屬性”:1},{“unique”:true,”dropDups”:true})

建立聯合索引:db.集合.ensureIndex({屬性:1,age:1})
檢視當前集合的所有索引:db.集合.getIndexes()
刪除索引:db.集合.dropIndex(`索引名稱`)

mongodb資料備份與恢復
mongodb資料備份
備份:mongodump -h dbhost -d dbname -o dbdirectory
-h: 伺服器地址,也可以指定埠號
-d: 需要備份的資料庫名稱
-o: 備份的資料存放位置,此目錄中存放著備份出來的資料
mongodb資料恢復
恢復:mongorestore -h dbhost -d dbname --dir dbdirectory
-h: 伺服器地址
-d: 需要恢復的資料庫例項
--dir: 備份資料所在位置

mongodb與python互動
安裝與匯入
安裝:pip install pymongo
匯入模組:from pymongo import MongoClient

例項化
例項化物件以連結資料庫,連線物件有host,port兩個引數。

from pymongo import MongoClient
class clientMongo:
    def __init__(self):
      client = MongoClient(host="127.0.0.1", port=27017)
      #使用[]括號的形式選擇資料庫和集合
      self.cliention = client["xianyu"]["xianyuplus"]
插入資料
插入單條資料:返回ObjectId

def item_inser_one(self):
  ret = self.cliention.insert({"xianyu":"xianyuplus","age":20})
  print(ret)
插入多條資料:

def item_insert_many(self):
  item_list = [{"name":"xianyuplus{}".format(i)} for i in range(10000)]
  items = self.cliention.insert_many(item_list)
查詢資料
查詢單條資料:

def item_find_one(self):
  ret = self.cliention.find_one({"xianyu":"xianyuplus"})
  print(ret)
查詢多條資料:

def item_find_many(self):
  ret = self.cliention.find({"xianyu":"xianyuplus"})
  for i in ret:
    print(i)
更新資料
**更新一條資料:**


def item_update_one(self):
  self.cliention.update_one({"xianyu":"xianyuplus"},{"$set":{"xianyu":"xianyu"}})
更新全部資料:

def item_update(self):
  self.cliention.update_many({"xianyu":"xianyuplus"},{"$set":{"xianyu":"xianyu"}})
刪除資料
刪除一條資料:

def item_delete_one(self):
  self.cliention.delete_one({"xianyu":"xianyuplus"})
刪除符合條件的資料:

def item_delete_many(self):
  self.cliention.delete_many({"xianyu":"xianyuplus"})

尾言
以上就是關於mongodb的一些用法,重點部分還是mongo高階查詢以及聚合管道,一定要review幾遍才記得住,本篇是python資料庫互動的最後一篇,希望對你有所幫助。

原文釋出時間為:2018-08-27
本文作者:煌金的鹹魚
本文來自雲棲社群合作伙伴“鹹魚普拉思”,瞭解相關資訊可以關注“鹹魚普拉思”。


相關文章