Python3 操作 MongoDB

一、安裝

pip3 install pymongo

二、基本使用

1. 導(dǎo)入模塊

import pymongo

2. 建立本地鏈接

cl = pymongo.MongoClient('localhost', 27017)

## 或者

cl = Mongocl('mongodb://localhost:27017/')


3. 獲取數(shù)據(jù)庫

一個(gè)MongoDB實(shí)例可以支持多個(gè)獨(dú)立的 數(shù)據(jù)庫。在使用PyMongo時(shí),您可以使用Mongocl實(shí)例上的屬性樣式訪問來訪問數(shù)據(jù)庫:

## 查看當(dāng)前都有那些庫
cl.database_names()

## 獲取數(shù)據(jù)庫對象
db = cl.test_database

或者

db = cl['test_database']


4. 獲取集合

一個(gè)集合是一組存儲(chǔ)在MongoDB中的文檔,并且可以被認(rèn)為是大致在關(guān)系數(shù)據(jù)庫中的表。
在 PyMongo 中獲取集合與獲取數(shù)據(jù)庫的工作方式相同:

## 查看當(dāng)前庫中都有那些集合
db.collection_names()

## 獲取集合對象
collection = db.test_collection

## 或者

collection = db['test-collection']

5 合法的集合名:

  • 集合名不能是空字符串""。
  • 集合名不能含有\(zhòng)0字符(空字符),這個(gè)字符表示集合名的結(jié)尾。
  • 集合名不能以"system."開頭,這是為系統(tǒng)集合保留的前綴。
  • 用戶創(chuàng)建的集合名字不能含有保留字符。有些驅(qū)動(dòng)程序的確支持在集合名里面包含,這是因?yàn)槟承┫到y(tǒng)生成的集合中包含該字符。除非你要訪問這種系統(tǒng)創(chuàng)建的集合,否則千萬不要在名字里出現(xiàn)$。

三、惰性機(jī)制

關(guān)于MongoDB中的集合(和數(shù)據(jù)庫)的一個(gè)重要注意事項(xiàng)是它們是懶惰地創(chuàng)建的。
上述命令都沒有在MongoDB服務(wù)器上實(shí)際執(zhí)行過任何操作。集合和數(shù)據(jù)庫在第一個(gè)文檔被插入時(shí)創(chuàng)建。

四、 文檔

MongoDB中的數(shù)據(jù)使用JSON樣式的文檔來表示(并存儲(chǔ))。
在PyMongo中,我們使用字典來表示 Mongo 中文檔。例如,以下字典可能用于表示博客文章:

In [34]: import datetime

In [35]: post = {"author": "yangge",
        "text": "云計(jì)算-NoSQL",
        "tags": ["mongodb", "python", "pymongo"],
        "date": datetime.datetime.now()}

請注意,文檔可以包含本機(jī)Python類型(如datetime.datetime實(shí)例),這些類型 將自動(dòng)轉(zhuǎn)換為適當(dāng)?shù)腂SON類型并從其中轉(zhuǎn)換

1 文檔特點(diǎn):

  • 文檔中的鍵/值對是有序的。
  • 文檔中的值不僅可以是在雙引號(hào)里面的字符串,還可以是其他幾種數(shù)據(jù)類型(甚至可以是整個(gè)嵌入的文檔)。
  • MongoDB區(qū)分類型和大小寫。
  • MongoDB的文檔不能有重復(fù)的鍵。
  • 文檔的鍵是字符串。除了少數(shù)例外情況,鍵可以使用任意UTF-8字符。

2 文檔鍵命名規(guī)范:

  1. 鍵不能含有\(zhòng)0 (空字符)。這個(gè)字符用來表示鍵的結(jié)尾。
  2. .和$有特別的意義,只有在特定環(huán)境下才能使用。
  3. 以下劃線"_"開頭的鍵是保留的(不是嚴(yán)格要求的)。

五、 插入文件數(shù)據(jù)

## 使用、創(chuàng)建了 posts 集合
In [36]: posts_col = db.posts 

## 向 psts 集合中插入一個(gè)文檔,并返回了 _id 對象
In [37]: post_id = posts_col.insert_one(post).inserted_id

In [38]: post_id
Out[38]: ObjectId('5a9f8eb2e138232b02854093')

In [41]: print(post_id)
5a9f8eb2e138232b02854093

In [42]: post_id.__str__()
Out[42]: '5a9f8eb2e138232b02854093'

驗(yàn)證

插入第一個(gè)文檔后,posts集合實(shí)際上已經(jīng)在服務(wù)器上創(chuàng)建。

我們可以通過列出數(shù)據(jù)庫中的所有集合來驗(yàn)證這一點(diǎn):

In [45]: db.collection_names(include_system_collections=False)
Out[45]: ['posts_col']

六、 使用find_one()獲取單個(gè)文檔

可以在MongoDB中執(zhí)行的最基本的查詢類型是 find_one()。

此方法返回與查詢匹配的單個(gè)文檔(如果沒有匹配,則返回None)。

當(dāng)您知道只有一個(gè)匹配的文檔,或者只對第一個(gè)匹配感興趣時(shí),它非常有用。

這里我們使用 find_one()從posts集合中獲取第一個(gè)文檔:

In [47]: posts_col.find_one()
Out[47]:
{'_id': ObjectId('5a9f8a6de138232b02854092'),
 'author': 'Mike',
 'date': datetime.datetime(2018, 3, 7, 6, 44, 54, 672000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': 'My first blog post!'}

指定匹配查詢

In [47]: posts_col.find_one(post)
Out[47]:
{'_id': ObjectId('5a9f8eb2e138232b02854093'),
 'author': 'yangge',
 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': '云計(jì)算-NoSQL'}
 ## --------------------------------------------------
 
 In [88]: posts_col.find_one({'author': 'yangge'})
Out[88]:
{'_id': ObjectId('5a9f8eb2e138232b02854093'),
 'author': 'yangge',
 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': '云計(jì)算-NoSQL'}

1 最好通過 _id_obj 查找

假如你創(chuàng)建了同樣的數(shù)據(jù)在 Mongo 里,他會(huì)同時(shí)存在,但是 _id 不一樣。

所以建議使用創(chuàng)建數(shù)據(jù)時(shí)返回的 _id 對象來查詢。

In [93]: posts_col.insert_one({"shark": "鯊魚"}).inserted_id
Out[93]: ObjectId('5a9f97d1e138232b02854094')

In [94]: posts_col.insert_one({"shark": "鯊魚"})
Out[94]: <pymongo.results.InsertOneResult at 0x7f74d652e388>

In [95]: shark_id = posts_col.insert_one({"shark": "鯊魚", "age": "18"}).inserted_id

In [96]: shark_id_obj = posts_col.insert_one({"shark": "鯊魚"}).inserted_id

In [97]: posts_col.find_one({"_id": shark_id_obj})
Out[97]: {'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鯊魚'}

In [98]: posts_col.find_one({"_id": shark_id})
Out[98]: {'_id': ObjectId('5a9f97fae138232b02854096'), 'shark': '鯊魚'}

## 注意有個(gè)空格哦
In [99]: posts_col.find_one({"shark": " 鯊魚"})

In [100]: posts_col.find_one({"shark": "鯊魚"})
Out[100]: {'_id': ObjectId('5a9f97d1e138232b02854094'), 'shark': '鯊魚'}

2 從字符串轉(zhuǎn)換為ObjectId

In [121]: from bson.objectid import ObjectId

In [122]: posts_col.find_one({'_id': ObjectId(shark_id_obj)})
Out[122]: {'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鯊魚'}

3 ==在 Python2 中==

MongoDB以BSON格式存儲(chǔ)數(shù)據(jù)。BSON字符串是UTF-8編碼的,所以PyMongo必須確保它存儲(chǔ)的任何字符串只包含有效的UTF-8數(shù)據(jù)。常規(guī)字符串(<type'str'>)被驗(yàn)證并保存不變。Unicode字符串(<type'unicode'>)首先被編碼為UTF-8。我們的示例字符串在Python shell中被表示為u'Mike'而不是'Mike',原因是PyMongo將每個(gè)BSON字符串解碼為Python unicode字符串,而不是常規(guī)str。

4 關(guān)于 _id

In [110]: shark_id.generation_time.isoformat()
Out[110]: '2018-03-07T07:42:50+00:00'

七、 批量插入

為了讓查詢更有趣,讓我們插入更多的文檔。除了插入單個(gè)文檔外,我們還可以通過將列表作為第一個(gè)參數(shù)傳遞給insert_many()來執(zhí)行批量插入操作。這會(huì)將每個(gè)文檔插入列表中,只向服務(wù)器發(fā)送一條命令:

簡單粗暴的上官方示例

>>> new_posts = [{"author": "Mike",
...               "text": "Another post!",
...               "tags": ["bulk", "insert"],
...               "date": datetime.datetime(2009, 11, 12, 11, 14)},
...              {"author": "Eliot",
...               "title": "MongoDB is fun",
...               "text": "and pretty easy too!",
...               "date": datetime.datetime(2009, 11, 10, 10, 45)}]
>>> result = posts_col.insert_many(new_posts)
>>> result.inserted_ids
[ObjectId('...'), ObjectId('...')]

八、 查詢多個(gè)文檔

我們使用find() 方法來獲取多個(gè)文檔 。
find() 返回一個(gè) Cursor實(shí)例,它允許我們遍歷所有匹配的文檔。

例如,我們可以迭代posts集合中的每個(gè)文檔:

In [129]: for post in posts_col.find():
     ...:     print(post)
     ...:
{'_id': ObjectId('5a9f8a6de138232b02854092'), 'author': 'Mike', 'text': 'My first blog post!', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 6, 44, 54, 672000)}
{'_id': ObjectId('5a9f8eb2e138232b02854093'), 'author': 'yangge', 'text': '云計(jì)算-NoSQL', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000)}
{'_id': ObjectId('5a9f97d1e138232b02854094'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f97e1e138232b02854095'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f97fae138232b02854096'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f9e48e138232b02854098'), 'author': 'Mike', 'text': 'Another post!', 'tags': ['bulk', 'insert'], 'date': datetime.datetime(2009, 11, 12, 11, 14)}
{'_id': ObjectId('5a9f9e48e138232b02854099'), 'author': 'Eliot', 'title': 'MongoDB is fun', 'text': 'and pretty easy too!', 'date': datetime.datetime(2009, 11, 10, 10, 45)}

就像我們用 find_one()所做的那樣,我們可以傳遞一個(gè)文檔給 find() 來限制返回的結(jié)果。
在這里,我們只得到那些作者是 "鯊魚" 的文檔:

In [133]: for post in posts_col.find({"shark": '鯊魚'}):
     ...:     print(post)
     ...:
{'_id': ObjectId('5a9f97d1e138232b02854094'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f97e1e138232b02854095'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f97fae138232b02854096'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鯊魚'}

九、計(jì)數(shù)

In [134]: posts_col.count()
Out[134]: 8

In [135]: posts_col.find({"author": "yangge"}).count()
Out[135]: 1

十、范圍查詢

MongoDB支持許多不同類型的高級(jí)查詢。例如,讓我們執(zhí)行查詢,將結(jié)果限制為比特定日期更早的帖子,還可以按作者對結(jié)果進(jìn)行排序

In [136]: d = datetime.datetime(2018, 11, 12, 12)

In [137]:  for post in posts_col.find({"date": {"$lt": d}}).sort("author"):
     ...:     print(post)
     ...:
{'_id': ObjectId('5a9f9e48e138232b02854099'), 'author': 'Eliot', 'title': 'MongoDB is fun', 'text': 'and pretty easy too!', 'date': datetime.datetime(2009, 11, 10, 10, 45)}
{'_id': ObjectId('5a9f8a6de138232b02854092'), 'author': 'Mike', 'text': 'My first blog post!', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 6, 44, 54, 672000)}
{'_id': ObjectId('5a9f9e48e138232b02854098'), 'author': 'Mike', 'text': 'Another post!', 'tags': ['bulk', 'insert'], 'date': datetime.datetime(2009, 11, 12, 11, 14)}
{'_id': ObjectId('5a9f8eb2e138232b02854093'), 'author': 'yangge', 'text': '云計(jì)算-NoSQL', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000)}

十一、排序

db.mycollection
mycol = db.mycollection
mycol.insert_one({'name': '姜文'})
result_dic = db.mycollection.find().sort("age")
for item in result_dic:
    print(item)

十二、更新

更新數(shù)據(jù)庫, ObjectId 需要引入

from bson.objectid import ObjectId
db.mycollection.update({'_id': ObjectId('59255118d92fac43dcb1999a')}, {'$set': {'name': '九筒'}})

十三、刪除

刪除指定數(shù)據(jù)

db.mycollection.remove({'name':'王二麻33333'})

刪除全部數(shù)據(jù)(慎用)

db.mycollection.remove()

十四、capped collections (擴(kuò)展)

Capped collections 就是固定大小的collection。

它有很高的性能以及隊(duì)列過期的特性(過期按照插入的順序). 有點(diǎn)和 "RRD" 概念類似。

Capped collections是高性能自動(dòng)的維護(hù)對象的插入順序。它非常適合類似記錄日志的功能 和標(biāo)準(zhǔn)的collection不同,你必須要顯式的創(chuàng)建一個(gè)capped collection, 指定一個(gè)collection的大小,單位是字節(jié)。collection的數(shù)據(jù)存儲(chǔ)空間值提前分配的。

要注意的是指定的存儲(chǔ)大小包含了數(shù)據(jù)庫的頭信息。

db.createCollection("mycoll", {capped:true, size:100000})
  • 在capped collection中,你能添加新的對象。
  • 能進(jìn)行更新,然而,對象不會(huì)增加存儲(chǔ)空間。如果增加,更新就會(huì)失敗 。
  • 數(shù)據(jù)庫不允許進(jìn)行刪除。使用drop()方法刪除collection所有的行。
  • 注意: 刪除之后,你必須顯式的重新創(chuàng)建這個(gè)collection。
  • 在32bit機(jī)器中,capped collection最大存儲(chǔ)為1e9( 1X109)個(gè)字節(jié)。

十五、元數(shù)據(jù)

數(shù)據(jù)庫的信息是存儲(chǔ)在集合中。它們使用了系統(tǒng)的命名空間:

dbname.system.*

在MongoDB數(shù)據(jù)庫中名字空間 <dbname>.system.* 是包含多種系統(tǒng)信息的特殊集合(Collection),如下:

集合命名空間 描述
dbname.system.namespaces 列出所有名字空間。
dbname.system.indexes 列出所有索引。
dbname.system.profile 包含數(shù)據(jù)庫概要(profile)信息。
dbname.system.users 列出所有可訪問數(shù)據(jù)庫的用戶。
dbname.local.sources 包含復(fù)制對端(slave)的服務(wù)器信息和狀態(tài)。

對于修改系統(tǒng)集合中的對象有如下限制。

  • {{system.indexes}} 插入數(shù)據(jù),可以創(chuàng)建索引。

  • 但除此之外該表信息是不可變的(特殊的 drop index 命令將自動(dòng)更新相關(guān)信息)。

  • {{system.users}} 是可修改的。

  • {{system.profile}} 是可刪除的。


十六、MongoDB 數(shù)據(jù)類型

下表為MongoDB中常用的幾種數(shù)據(jù)類型。

數(shù)據(jù)類型 描述
String 字符串。存儲(chǔ)數(shù)據(jù)常用的數(shù)據(jù)類型。在 MongoDB 中,UTF-8 編碼的字符串才是合法的。
Integer 整型數(shù)值。用于存儲(chǔ)數(shù)值。根據(jù)你所采用的服務(wù)器,可分為 32 位或 64 位。
Boolean 布爾值。用于存儲(chǔ)布爾值(真/假)。
Double 雙精度浮點(diǎn)值。用于存儲(chǔ)浮點(diǎn)值。
Min/Max keys 將一個(gè)值與 BSON(二進(jìn)制的 JSON)元素的最低值和最高值相對比。
Array 用于將數(shù)組或列表或多個(gè)值存儲(chǔ)為一個(gè)鍵。
Timestamp 時(shí)間戳。記錄文檔修改或添加的具體時(shí)間。
Object 用于內(nèi)嵌文檔。
Null 用于創(chuàng)建空值。
Symbol 符號(hào)。該數(shù)據(jù)類型基本上等同于字符串類型,但不同的是,它一般用于采用特殊符號(hào)類型的語言。
Date 日期時(shí)間。用 UNIX 時(shí)間格式來存儲(chǔ)當(dāng)前日期或時(shí)間。你可以指定自己的日期時(shí)間:創(chuàng)建 Date 對象,傳入年月日信息。
Object ID 對象 ID。用于創(chuàng)建文檔的 ID。
Binary Data 二進(jìn)制數(shù)據(jù)。用于存儲(chǔ)二進(jìn)制數(shù)據(jù)。
Code 代碼類型。用于在文檔中存儲(chǔ) JavaScript 代碼。
Regular expression 正則表達(dá)式類型。用于存儲(chǔ)正則表達(dá)式。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、MongoDB簡介 1.概述 ? MongoDB是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫,由C++語言編寫。旨在為WE...
    鄭元吉閱讀 1,130評(píng)論 0 2
  • MongoDB文檔 MongoDB 概念解析 不管我們學(xué)習(xí)什么數(shù)據(jù)庫都應(yīng)該學(xué)習(xí)其中的基礎(chǔ)概念,在mongodb中基...
    birdflying閱讀 2,073評(píng)論 0 27
  • MongoDB的介紹 MongoDB 是由C++語言編寫的,是一個(gè)基于分布式文件存儲(chǔ)的開源數(shù)據(jù)庫系統(tǒng) 在高負(fù)載的情...
    Luo_Luo閱讀 1,862評(píng)論 0 2
  • 簡介 MongoDB 是一個(gè)基于分布式文件存儲(chǔ)的NoSQL數(shù)據(jù)庫 由C++語言編寫,運(yùn)行穩(wěn)定,性能高 旨在為 WE...
    大熊_7d48閱讀 37,870評(píng)論 1 9
  • NoSql數(shù)據(jù)庫優(yōu)缺點(diǎn) 在優(yōu)勢方面主要體現(xiàn)在下面幾點(diǎn): 簡單的擴(kuò)展 快速的讀寫 低廉的成本 靈活的數(shù)據(jù)模型 在不足...
    dreamer_lk閱讀 2,878評(píng)論 0 6

友情鏈接更多精彩內(nèi)容