一、介紹
1. MongoDB 概述
MongoDB 是一款由 C++ 語言編寫的開源 NoSQL 數據庫,采用分布式文件存儲設計。作為介于關系型和非關系型數據庫之間的產品,它是 NoSQL 數據庫中最接近傳統關系數據庫的解決方案,同時保留了 NoSQL 的靈活性和擴展性。
核心特性:
-
文檔導向存儲:數據以類似 JSON 的 BSON 格式存儲
-
無固定表結構:不需要預先定義嚴格的表結構
-
多語言支持:提供 Python、Node.js、Java、C++、PHP、C# 等主流語言的驅動
-
應用場景廣泛:適用于大數據、內容管理、持續交付、移動應用、社交網絡、用戶數據管理等領域
2. MongoDB 相對于關系型數據庫(RDBMS)的優勢
優勢 | 說明 |
---|---|
靈活的數據模型 | 無固定結構,數據結構為鍵值對(key:value)形式,文檔類似 JSON 對象 |
嵌套數據支持 | 字段值可包含其他文檔、數組及文檔數組,使數據結構更清晰 |
無復雜關聯 | 不需要維護表與表之間的內在關聯關系,簡化數據模型 |
強大的查詢能力 | 提供類似 SQL 的豐富查詢功能,支持基于文檔的動態查詢 |
高性能與可擴展 | 易于調優和擴展,具備高性能、高可用性和可伸縮性特性 |
對象映射自然 | 應用程序對象與數據庫對象呈現天然對應關系 |
存儲方式靈活 | 支持基于內存或硬盤文件的存儲方式 |
完善的特性支持 | 提供豐富的查詢操作、索引支持,4.0+版本支持多文檔事務 |
3. SQL 與 MongoDB 核心概念對比
SQL 術語 | MongoDB 術語 | 說明 |
---|---|---|
數據庫 (Database) | 數據庫 (Database) | 數據存儲的最高層級 |
表 (Table) | 集合 (Collection) | 數據記錄的容器 |
行/記錄 (Row) | 文檔 (Document) | 單條數據記錄,采用 JSON 結構 |
列/字段 (Column) | 字段/鍵 (Field) | 數據記錄的屬性 |
主鍵 (Primary Key) | 對象ID (ObjectId) | 默認主鍵格式為?_id: ObjectId("...") |
索引 (Index) | 索引 (Index) | 加速查詢的數據結構 |
4. 適用場景推薦
MongoDB 特別適合以下場景:
-
需要快速迭代開發的項目
-
數據結構頻繁變化的業務
-
處理大量非結構化或半結構化數據
-
需要水平擴展的高流量應用
-
內容管理系統和博客平臺
-
實時分析和數據處理
傳統 SQL 仍更適合:
-
需要復雜事務處理的應用
-
數據結構高度規范化的場景
-
已有成熟的關系型數據模型
提示:MongoDB 4.0+ 已支持多文檔 ACID 事務,但在復雜事務場景下仍需謹慎評估性能影響。
?
二、MongoDB基本操作
1.庫管理
顯示所有數據庫列表:空數據庫不會顯示,或者說空數據庫已經被MongoDB回收了。
show dbs
show databases
切換數據庫,如果數據庫不存在則創建數據庫
use <database>
查看當前工作的數據庫
db //是db.getName()的簡寫
刪除當前數據庫,如果數據庫不存在,也會返回{"ok":1}
use <db> // 先切換到要刪除的數據庫種,然后才能刪除數據庫
db.dropDatabase()
查看當前數據庫狀態
db.stats()
在 MongoDB 中,最重要的核心是文檔,如果一個庫或者一個庫下的集合中的文檔全部被刪除了,則這個庫和這個集合就會 MongoDB回收刪除。
2.集合管理
創建集合
在 mongodb 中其實不需要專門創建集合,直接添加文檔,mongodb 也會自動生成集合
// name 為必填參數,options為可選參數。capped若設置值為true,則size必須也一并設置
db.createCollection(name=<集合名稱>,options={capped:<boolean>, // 創建固定集,固定集指限制固定數據大小的集合,當數據達到最大值會自動覆蓋最早的文檔內容size:<bytes_size>, // 指定固定集合存儲的最大字節數,單位:字節數max:<collection_size> // 指定固定集合中包含文檔的最大數量,單位:字節數});// 添加文檔到不存在的集合中,mongodb會自動創建集合,
// db.<集合名稱>.insert(要存儲的json數據)use book_info
db.courses.insert({"name":"python入門","price":31.4})
集合列表
show collections // 或 show tables 或 db.getCollectionNames()
刪除集合
db.集合名稱.drop()
查看集合
db.getCollection("集合")
db.集合名稱
查看集合創建信息
db.printCollectionStats()
三、文檔管理
1.數據類型
類型 | 描述 |
---|---|
ObjectID | 用于存儲文檔的ID,相當于主鍵,區分文檔的唯一字段,MongoDB中就是一個對象的返回值 |
String | 字符串是最常用的數據類型,MongoDB中的字符串必須是UTF-8. |
Integer | 整數類型用于存儲數值。整數可以是32位,也可以是64位,這取決于你的服務器。 |
Double | 雙精度類型用于存儲浮點值,MongoDB中沒有float浮點數這個說法 |
Boolean | 布爾類型用于存儲布爾值:true/false |
Arrays | 將數組、列表或多個值存儲到一個鍵 |
Timestamp | 時間戳,用于記錄文檔何時被修改或創建。Date(),Timestamp(),ISODate() |
Object | 用于嵌入文檔, 相當于子屬性是另一個 |
Null | 空值,相當于 |
Symbol | 與字符串用法相同,常用于某些使用特殊符號的語言,二進制 |
Date | 用于以 |
Binary data | 二進制數據,常用于保存文件的內容,往往是圖片,數據本身。 |
Code | 用于將 JavaScript代碼存儲到文檔中 |
Regular expression | 正則表達式 |
2.添加文檔
文檔的數據結構和JSON基本一樣。所有存儲在集合中的數據在內部存儲的格式都是BSON格式。
BSON是一種類似 JSON 的二進制形式的存儲格式,是 Binary JSON 的簡稱。
//添加文檔
//方式1
db.<集合名稱>.insert(<document>) // document就是一個json格式的數據//方式2
db.<集合名稱>.insertOne(<document>) // 如果文檔存在_id主鍵為更新數據,否則就添加數據。//方式3
//一次性添加多個文檔,多次給同一個集合
db.<集合名稱>.insertMany([<document>,<document>,...])
use person// 添加一條數據
db.user_list.insert({"name":"老李", "age":33, "sex":true, "child":{"name":"小灰灰","age":3}});
// WriteResult({ "nInserted" : 1 })// 添加一條數據
db.user_list.insertOne({"name":"小張", "age":18, "sex":true});
// {
// "acknowledged" : true,
// "insertedId" : ObjectId("605021e6d5c7a55cc95c1cb7")
// }// 添加多條數據
document1 = {"name":"小藍", "age":16}
document2 = {"name":"小廣", "age":16}
db.user_list.insertMany([document1, document2]);// {
// "acknowledged" : true,
// "insertedIds" : [
// ObjectId("60502235d5c7a55cc95c1cba"),
// ObjectId("60502235d5c7a55cc95c1cbb")
// ]
// }
db.user_list.find()
3.刪除文檔
// 方式1
db.<集合名稱>.remove(<query>, // remove的條件,一般寫法:{"屬性":{條件:值}},如果不填寫條件,刪除所有文檔{justOne: <boolean>, // 可選刪除,是否只刪除查詢到的第一個文檔,默認為false,刪除所有writeConcern: <document> // 可選參數,拋出異常的級別。}
)// 方式2: 刪除一條數據
db.<集合名稱>.deleteOne(<query>, // removed的條件,一般寫法:{"屬性":{條件:值}},如果不填寫條件,刪除所有文檔{justOne: <boolean>, // 可選刪除,是否只刪除查詢到的第一個文檔,默認為false,刪除所有writeConcern: <document> // 可選參數,拋出異常的級別。}
)
// 方式3:刪除多條數據
db.<集合名稱>.deleteMany(<query>, // removed的條件,一般寫法:{"屬性":{條件:值}},如果不填寫條件,刪除所有文檔{justOne: <boolean>, // 可選刪除,是否只刪除查詢到的第一個文檔,默認為false,刪除所有writeConcern: <document> // 可選參數,拋出異常的級別。}
)
// 添加多條測試數據
document1 = {"name":"小黑", "age":16}
document2 = {"name":"小白", "age":16}
db.user_list.insertMany([document1, document2]);// 刪除滿足條件的第一條數據
// 條件 {"age":{$eq:16}} 相當于 age == 16
// db.user_list.remove({"age":{$eq:16}},{"justOne":true})
// 刪除滿足條件的所有數據,條件中$wq可以不寫
// db.user_list.remove({"age":16}); // 等于可以省略不寫,相當于 db.user_list.remove({"age":{$eq:16}});// 刪除一條
db.user_list.deleteOne({"age": 16})
// 刪除多條
db.user_list.deleteMany({"age": 16})
4.查詢文檔
// 獲取一條
db.集合名稱.findOne(<query>, // 查詢條件,刪除、查詢、修改都需要條件、條件寫法基本一樣的。{<key>: 0, // 隱藏指定字段,例如:"_id":0,<key>: 1, // 顯示指定字段,例如:"title":1,....}
)
// 獲取多條
db.集合名稱.find(<query>, // 查詢條件{<key>: 0, // 隱藏指定字段,例如:"_id":0,<key>: 1, // 顯示指定字段,例如:"title":1,....}
)// 以易讀的方式來格式化顯示讀取到的數據,只能在find方法后面使用。
db.集合名稱.find().pretty()
// 切換數據庫
use person// 添加測試數據
docs = [{"name": "小黃", "sex": 0, "age": 15, "mobile": "13301234568"},{"name": "小飛", "sex": 1, "age": 16, "mobile": "1351234568"},{"name": "小龍", "sex": 1, "age": 19, "mobile": "15001234568"},{"name": "小綿羊", "sex": 0, "age": 13, "mobile": "15001234568"}
]
db.user_list.insertMany(docs);// 查詢一條數據
db.user_list.findOne() // 獲取集合中第一條數據
db.user_list.findOne({}) // 同上
db.user_list.findOne({},{_id:0}) // 獲取集合中第一條數據,并隱藏_id
db.user_list.findOne({},{_id:0, name:1, mobile:1}) // 獲取集合中第一條數據,只查詢文檔的name和mobile屬性的數據
db.user_list.findOne({name:"小飛"}, {_id:0, name:1, mobile:1})
db.user_list.findOne({name:"小龍", age:19})// 查詢多條數據
db.user_list.find()
db.user_list.find().pretty()
db.user_list.find({sex:1})
db.user_list.find({sex:0}, {_id:0, name:1, mobile:1})
5.比較運算
操作 | 格式 | 語法例子 |
|
等于 |
|
|
|
小于 |
|
|
|
小于或等于 |
|
|
|
大于 |
|
|
|
大于或等于 |
|
|
|
不等于 |
|
|
|
包含 |
|
|
|
db.user_list.find({"age": {$lte:18}}) // 小于等于
db.user_list.find({"age": {$gte:18}}) // 大于等于
db.user_list.find({"age": {$in:[16,33]}})// 添加測試數據
db.user_list.insert({"name":"老王", "age":32, "sex":true, "child":{"name":"小王", "age":4}});
db.user_list.insert({"name":"老張", "age":33, "sex":true, "child":{"name":"小張", "age":5}});db.user_list.find({"child.age": {$gt:3}})
db.user_list.find({"child.age": {$in:[3, 5]}})
6.邏輯運算
|
|
|
|
|
|
|
|
|
|
|
|
// 查詢age=19 并且 sex=1
db.user_list.find({$and:[{"age":{$eq:19}},{"sex":{$eq:1}}]
})
// 簡寫:
db.user_list.find({$and:[{"age":19},{"sex":1}]
})
// 繼續簡寫;
db.user_list.find({"age":19, "sex":1})// 查詢age=16或者age=18
db.user_list.find({$or:[{"age":{$eq:16}},{"age":{$eq:18}}]
})// 查詢年齡!=16的
db.user_list.find({"age":{$not:{$eq:16}}})
db.user_list.find({"age":{$ne:16}})// 查詢age=33的男生 或者 age=19的男生
db.user_list.find({"sex":1,$or:[{"age":19},{"age":33}]
});db.user_list.find({"sex":1,"age":{$in:[19,33]}
});db.user_list.find({$or:[{$and:[{"sex":1},{"age":19}]},{$and:[{"sex":1},{"age":33}]},]
});db.user_list.find({$or:[{"sex":1,"age":19},{"sex":1,"age":33},]
});
?7.排序顯示
db.集合.find().sort({<key>:1}) // 升序,默認為升序,從小到大
db.集合.find().sort({<key>:-1}) // 倒序db.user_list.find().sort({age:-1});
db.user_list.find().sort({age:-1, sex:1});
8.字段投影
find()方法默認將返回文檔的所有數據,但是可以通過設置find()的第二個參數projection,設置值查詢部分數據。
// 只顯示人名
db.user_list.find({},{'name':1,'_id':0})
9.分頁查詢
limit方法用于限制返回結果的數量,skip方法用于設置返回結果的開始位置
// db.集合.find(...).limit(結果數量).skip(跳過數量)db.user_list.find({},{"_id":0,"name":1,"age":1}).sort({"age":1}).limit(5);
db.user_list.find({},{"_id":0,"name":1,"age":1}).sort("age":1}).limit(5).skip(5);
10.更新文檔
操作 | 語法 | 說明 |
|
| 更新 |
|
| 更新 |
|
| 移除 |
|
| 給 |
|
| 與 |
|
| 給 |
// db.user_list.insert({"name":"老李", "age":33, "sex":true, "child":{"name":"小灰灰","age":3}});
// $inc
// 把老李的年齡加10歲
db.user_list.update({"name":"老李"},{$inc:{"age":10}}); // 更新一條
db.user_list.find({"name": "老李"})// 添加測試數據
documents = [{"name":"小明", "age":12},{"name":"小明", "age":20},
]
db.user_list.insertMany(documents)db.user_list.updateMany({"name":"小明"},{$inc:{"age":10}}); // 更新多條// 把老李的孩子年齡加10歲
db.user_list.update({"name":"老李"},{$inc:{"child.age":10}});// $set
//更新老李的手機號碼
db.user_list.update({"name":"老李"},{$set:{"mobile":"18012312312"}}); // 更新一條
// 更新老李孩子的手機號碼
db.user_list.update({"name":"老李"},{$set:{"child.mobile":"18012312312"}});// $unset
// 移除老李的性別鍵值對
db.user_list.update({"name":"老李"},{$unset:{"sex":true}});// $push
db.user_list.update({"name":"老李"},{$set:{"love":["TV","game"]}});
db.user_list.update({"name":"老李"},{$push:{"love":"code"}}); // 往列表屬性中追加成員// $addToSet 結合 $each 批量添加列表中的每一個元素
db.user_list.update({"name":"老李"},{$addToSet:{"love":{$each:["code","music","TV"]}}});// $pull
db.user_list.update({"name":"老李"},{$pull:{"love":"TV"}});// $pop
db.user_list.update({"name":"老李"},{$pop:{"love":-1}}); // 左邊移除列表的第一個成員
db.user_list.update({"name":"老李"},{$pop:{"love":1}}); // 右邊移除列表的最后一個成員// $rename 字段名重命名
db.user_list.update({"name":"老李"},{$rename:{"love":"lve"}});
?四、第三方客戶端-pymongo
1.概述
pymongo 是 MongoDB的一個 python 驅動程序,允許你使用 python 來操作 mongodb 數據庫。下面將為你介紹pymongo的基本使用,包括安裝、連接數據庫、創建集合、插入文檔、查詢文檔、更新文檔和刪除文檔。
2.連接數據庫
需要安裝pymongo:pip install pymongo
from pymongo import MongoClientclient = MongoClient('localhost', 27017) # 連接到本地MongoDB
db = client['py_spider'] # 選擇或創建一個數據庫
3.文檔插入
插入數據時如果集合不存在則新建集合
from pymongo import MongoClientmongo_client = MongoClient()
collection = mongo_client['py_spider']['person']# 插入單個文檔
person_info = {"name": "John", "address": "長沙"}
collection.insert_one(person_info)# 插入多個文檔
person_info_list = [{"name": "Amy", "address": "上海"},{"name": "Hannah", "address": "南京"},{"name": "Joe", "address": "上海"}
]
collection.insert_many(person_info_list)
4.文檔查詢
使用
find_one()
方法查詢單個文檔,或者使用find()
查詢滿足條件的多個文檔。
# 查詢單個文檔
query = {"name": "John"}
document = collection.find_one(query)
print(document)# 查詢多個文檔
query = {}
documents = collection.find(query)
for document in documents:print(document)
5.更新文檔
使用
update_one()
方法更新單個文檔,或者使用update_many()
更新多個文檔。
# 更新單個文檔
query = {"name": "John"}
new_values = {"$set": {"address": "杭州"}}
collection.update_one(query, new_values)# 更新多個文檔
query = {"address": {"$regex": "上海"}}
new_values = {"$set": {"name": "Minnie"}}
collection.update_many(query, new_values)
6.刪除文檔
使用
delete_one()
方法刪除單個文檔,或者使用delete_many()
刪除多個文檔。
# 刪除單個文檔
query = {"address": "杭州"}
collection.delete_one(query)# 刪除多個文檔
query = {"address": {"$regex": "^上"}}
collection.delete_many(query)