摘要:刪除符合值為的第一條數(shù)據(jù)刪除符合值為的所有數(shù)據(jù)值得一提的是,刪除操作并不會改變的索引設置,即便刪除了這個下的所有文檔。因此這類批量執(zhí)行指令是非原子性的。官方推薦使用前者。在設計數(shù)據(jù)模型時,要考慮根據(jù)不同情況選擇適合的文檔結構進行設計。
1. 基礎概念 1.1 database
數(shù)據(jù)庫,一個數(shù)據(jù)倉庫可以包含多個集合
1.2 collection集合,類似于關系數(shù)據(jù)庫中的表。一個集合可以包含多個文檔。
capped collection(限制集合):設定空間上線,循環(huán)寫入,新數(shù)據(jù)覆蓋舊數(shù)據(jù)
1.3 document文檔,一個文檔保存著一份數(shù)據(jù)記錄。
1.3.1 數(shù)據(jù)校驗一個集合下的文檔,不會默認要求它們具有相同的數(shù)據(jù)模式。也就是說,同一個集合下的多個文檔:1.字段可以不同;2.同名字段的類型可以不同;相反,如果對文檔數(shù)據(jù)類型有要求,可以在創(chuàng)建集合時設置validator(例如使用JSON schema)來限制集合下文檔的數(shù)據(jù)類別。
1.3.2 文檔格式文檔使用BSON來存儲,BSON是JSON的二進制表現(xiàn)形式,因此可以適應更多的數(shù)據(jù)類型。
存儲在文檔的數(shù)據(jù)格式,與JSON類似,以鍵值對的形式存儲。
默認主鍵_id,為ObjectId類型。
使用insert_one()方法
book = { "name": "computer_science", "page": 238, } result = db.books.insert_one(book) _id = result.inserted_id # 返回插入項的id,類型為ObjectId2.1.2 多條插入
使用insert_many()方法
results = db.collection_name.insert_many([document1, document2, ...]) id_list = results.inserted_ids # 返回插入項的id列表,列表元素為ObjectId2.1.3 廢棄的插入方法
從pymongo3.0版本開始,已經不推薦使用insert()方法插入數(shù)據(jù),雖然它能同時滿足單條或多條數(shù)據(jù)的處理需求。
官方建議使用insert_one()和insert_many()來執(zhí)行替代操作
假設預先執(zhí)行了數(shù)據(jù)插入:
db.inventory.insert_many([ {"item": "journal", "qty": 25, "size": {"h": 14, "w": 21, "uom": "cm"}, "status": "A"}, {"item": "notebook", "qty": 50, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "A"}, {"item": "paper", "qty": 100, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "D"}, {"item": "planner", "qty": 75, "size": {"h": 22.85, "w": 30, "uom": "cm"}, "status": "D"}, {"item": "postcard", "qty": 45, "size": {"h": 10, "w": 15.25, "uom": "cm"}, "status": "A"}])2.2.1 基本查詢操作
使用find()方法執(zhí)行查詢,返回游標cursor
查詢所有記錄時,find()內的filter參數(shù)為空
cursor = db.inventory.find({})
上述查詢,類似于關系數(shù)據(jù)庫SQL語句:
SELECT * FROM inventory
cursor = db.inventory.find({"status": "D"})
上述查詢語句,類似于關系數(shù)據(jù)庫SQL語句:
SELECT * FROM inventory WHERE status = "D"
包含(IN)關系查詢
cursor = db.inventory.find({"status": {"$in": ["A", "D"]}})
上述查詢語句,類似于關系數(shù)據(jù)庫SQL語句:
SELECT * FROM inventory WHERE status in ("A", "D")
與(AND)關系查詢
cursor = db.inventory.find({"status": "A", "qty": {"$lt": 30}})
上述查詢語句,類似于關系數(shù)據(jù)庫SQL語句:
SELECT * FROM inventory WHERE status = "A" AND qty < 30
或(OR)關系查詢
cursor = db.inventory.find({"$or": [{"status": "A"}, {"qty": {"$lt": 30}}]})
上述查詢語句,類似于關系數(shù)據(jù)庫SQL語句:
SELECT * FROM inventory WHERE status = "A" OR qty < 30
在查詢中同時使用AND和OR
cursor = db.inventory.find({ "status": "A", "$or": [{"qty": {"$lt": 30}}, {"item": {"$regex": "^p"}}]})
上述查詢語句,類似于關系數(shù)據(jù)庫SQL語句:
SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")2.2.2 查詢操作符
查詢操作符定義了查詢條件,如:大于、等于、小于等,以下是整理的查詢操作符及說明:
比較操作符 | 說明 |
---|---|
$eq | 等于 |
$gt | 大于 |
$gte | 大于等于 |
$in | 包含 |
$lt | 小于 |
$lte | 小于等于 |
$ne | 不等于 |
$nin | 不包含于 |
邏輯操作符 | 說明 |
---|---|
$and | 與 |
$not | 非 |
$nor | 或非 |
$or | 或 |
元素操作符 | 說明 |
---|---|
$exists | 指定field存在 |
$type | 指定field的type |
查看field的type類型說明
其他操作符說明請見:Query and Projection Operators
2.2.3 嵌套文檔查詢對于文檔中存在的嵌套結構的查詢,可以對文檔中的嵌套結構進行 匹配查詢 ,也可以對嵌套內容中的某個字段進行 嵌套字段查詢
假設文檔數(shù)據(jù)如下:
from bson.son import SON db.inventory.insert_many([ {"item": "journal", # 物品名稱 "qty": 25, # 數(shù)量 "size": SON([("h", 14), ("w", 21), ("uom", "cm")]), # 嵌套結構(高度,寬度,度量單位) "status": "A"}, # 狀態(tài) {"item": "notebook", "qty": 50, "size": SON([("h", 8.5), ("w", 11), ("uom", "in")]), "status": "A"}, {"item": "paper", "qty": 100, "size": SON([("h", 8.5), ("w", 11), ("uom", "in")]), "status": "D"}, {"item": "planner", "qty": 75, "size": SON([("h", 22.85), ("w", 30), ("uom", "cm")]), "status": "D"}, {"item": "postcard", "qty": 45, "size": SON([("h", 10), ("w", 15.25), ("uom", "cm")]), "status": "A"}])
對嵌套結構進行匹配查詢
from bson.son import SON cursor = db.inventory.find( {"size": SON([("h", 14), ("w", 21), ("uom", "cm")])}) # 上述查詢語句中的filter條件,需要完全匹配嵌套文檔中的內容,否則無法查詢到相關記錄。
對嵌套結構中的字段進行查詢
mongo使用點表示法指定文檔中的嵌套字段:"field.nested_field"
# 查詢嵌套字段uom的值為cm的記錄 cursor = db.inventory.find({"size.uom": "cm"}) # 使用操作符查詢高度大于10的記錄 cursor = db.inventory.find({"size.h": {"$gt": 10}}) # 多個字段的復合查詢 cursor = db.inventory.find( {"size.h": {"$lt": 15}, "size.uom": "in", "status": "D"})2.2.4 數(shù)組類型查詢
假設向collection中插入如下數(shù)據(jù)
db.inventory.insert_many([ {"item": "journal", "qty": 25, "tags": ["blank", "red"], "dim_cm": [14, 21]}, {"item": "notebook", "qty": 50, "tags": ["red", "blank"], "dim_cm": [14, 21]}, {"item": "paper", "qty": 100, "tags": ["red", "blank", "plain"], "dim_cm": [14, 21]}, {"item": "planner", "qty": 75, "tags": ["blank", "red"], "dim_cm": [22.85, 30]}, {"item": "postcard", "qty": 45, "tags": ["blue"], "dim_cm": [10, 15.25]}])
與2.2.3中嵌套文檔查詢類似,可以對整個數(shù)組進行 匹配查詢 , 也可以對數(shù)組中的某個元素進行查詢
匹配整個數(shù)組
cursor = db.inventory.find({"tags": ["red", "blank"]})
查詢數(shù)組中的某個元素
# 所有tags中包含red元素的數(shù)組都會被查詢到 cursor = db.inventory.find({"tags": "red"}) # 對數(shù)組中某個元素進行條件查詢 # dim_cm中任意一個元素大于25的記錄查詢 cursor = db.inventory.find({"dim_cm": {"$gt": 25}})
數(shù)組元素的復合條件查詢
查詢dim_cm中的某個元素能同時滿足大于15小于20的查詢條件的記錄
或者 dim_cm中的一個元素大于15,并且存在另一個元素小于20的記錄
# 這種查詢是不限制單個數(shù)組元素的,多個數(shù)組元素分別滿足查詢條件亦可 cursor = db.inventory.find({"dim_cm": {"$gt": 15, "$lt": 20}})
若要指定數(shù)組中某一個元素滿足多個查詢條件,需要使用 __$elemMatch__操作符來進行查詢
# 查詢數(shù)組中存在某一個元素同時滿足大于22并且小于30 cursor = db.inventory.find( {"dim_cm": {"$elemMatch": {"$gt": 22, "$lt": 30}}})
根據(jù)數(shù)組索引位置查詢
查詢dim_cm的第一個元素大于25的記錄
cursor = db.inventory.find({"dim_cm.1": {"$gt": 25}})
根據(jù)數(shù)組長度查詢
查詢數(shù)組長度是否符合查詢條件,需要使用 $size 操作符
查詢所有tags長度等于3的的記錄
cursor = db.inventory.find({"tags": {"$size": 3}})2.2.5 數(shù)組內的嵌套文檔查詢
假設向collection中插入如下數(shù)據(jù):
from bson.son import SON db.inventory.insert_many([ {"item": "journal", "instock": [ SON([("warehouse", "A"), ("qty", 5)]), SON([("warehouse", "C"), ("qty", 15)])]}, {"item": "notebook", "instock": [ SON([("warehouse", "C"), ("qty", 5)])]}, {"item": "paper", "instock": [ SON([("warehouse", "A"), ("qty", 60)]), SON([("warehouse", "B"), ("qty", 15)])]}, {"item": "planner", "instock": [ SON([("warehouse", "A"), ("qty", 40)]), SON([("warehouse", "B"), ("qty", 5)])]}, {"item": "postcard", "instock": [ SON([("warehouse", "B"), ("qty", 15)]), SON([("warehouse", "C"), ("qty", 35)])]}])
可以看到instock數(shù)組內部每一個元素都是一個嵌套文檔。對這類數(shù)據(jù)的查詢方法,是2.2.3嵌套文檔查詢和2.2.4數(shù)組類型查詢的結合。
對數(shù)組內某個嵌套文檔進行 匹配查詢
# 匹配查詢對于嵌套文檔內的field順序有要求, # 查詢結果只展示與查詢條件中field排列順序相同的記錄。 cursor = db.inventory.find( {"instock": SON([("warehouse", "A"), ("qty", 5)])})
對數(shù)組內的嵌套文檔字段進行 條件查詢
# 查詢所有文檔中,instock數(shù)組中至少有一個元素的qty值大于20的記錄 cursor = db.inventory.find({"instock.qty": {"$lte": 20}})
對數(shù)組形式的嵌套文檔按照 數(shù)組索引查詢
# 查詢所有文檔中,instock數(shù)組的第0個嵌套文檔元素中,qty的值小于等于20的所有記錄 cursor = db.inventory.find({"instock.0.qty": {"$lte": 20}})
使用 $elemMatch 對數(shù)組內的某個嵌套文檔進行復合查詢
# 數(shù)組內的某個文檔同時滿足qty=5并且warehouse值為A的查詢條件 cursor = db.inventory.find( {"instock": {"$elemMatch": {"qty": 5, "warehouse": "A"}}}) # 數(shù)組內的某個文檔的qty值大于10并且小于等于20 cursor = db.inventory.find( {"instock": {"$elemMatch": {"qty": {"$gt": 10, "$lte": 20}}}})2.2.6 指定查詢結果返回的field
MonogDB返回的查詢結果,默認包含文檔中所有的field,使用者可以通過讓mongo返回指定的field,來限制返回內容的數(shù)量。
查詢表達式如下:
# 返回指定的field cursor = db.inventory.find( {"status": "A"}, {"item": 1, "status": 1, "size.uom": 1}) # 不返回指定的field cursor = db.inventory.find({"status": "A"}, {"size.uom": 0, "status": 0}) # 對于數(shù)組形式的field,指定只返回最后一個元素(使用$slice操作符) cursor = db.inventory.find( {"status": "A"}, {"instock": {"$slice": -1}})2.2.7 查詢空值和field是否存在
查詢item為空或item字段不存在
cursor = db.inventory.find({"item": None})
只查詢字段為空的記錄
type值參照
# type值為10時表示的是null類型 cursor = db.inventory.find({"item": {"$type": 10}})
查詢某字段不存在
# 查詢所有文檔中,沒有item字段的記錄 cursor = db.inventory.find({"item": {"$exists": False}})2.3 更新數(shù)據(jù)
MongoDB提供了一系列的操作符來幫助完成文檔數(shù)據(jù)更新,具體說明可查看鏈接:https://docs.mongodb.com/manu...
2.3.1 更新單個文檔使用pymongo的update_one方法
db.inventory.update_one( {"item": "paper"}, # filter篩選條件, 只更新符合該條件的第一條數(shù)據(jù) {"$set": {"size.uom": "cm", "status": "P"}, "$currentDate": {"lastModified": True}}) # 數(shù)據(jù)更新表達式,使用$set操作符來更新數(shù)據(jù)2.3.2 更新多個文檔
使用pymongo的update_many()方法
db.inventory.update_many( {"qty": {"$lt": 50}}, # filter篩選條件,更新符合該條件的所有數(shù)據(jù) {"$set": {"size.uom": "in", "status": "P"}, "$currentDate": {"lastModified": True}})# 數(shù)據(jù)更新表達式,同樣使用$set操作符來更新數(shù)據(jù)2.3.3 替換文檔
使用pymongo的replace()方法
注:替換方法只替換除_id以外的其他字段
db.inventory.replace_one( {"item": "paper"}, # filter篩選條件,替換符合該條件的第一條數(shù)據(jù) {"item": "paper", # 替換后的文檔數(shù)據(jù) "instock": [ {"warehouse": "A", "qty": 60}, {"warehouse": "B", "qty": 40}]})2.3.4 upsert選項
不論是update_one()方法還是update_many()方法,亦或是replace_one()方法,都包含upsert:bool 選項,當upsert為True時,這些方法將具備在filter未篩選到文檔時,執(zhí)行文檔插入的能力。
2.4 刪除數(shù)據(jù)pymongo提供了delete_one()和delete_many()兩種方法執(zhí)行刪除操作。其中,delete_one()方法一次執(zhí)行一條文檔的刪除任務,delete_manyI()可執(zhí)行多條文檔刪除任務。
db.inventory.delete_one({"status": "D"}) # 刪除符合status值為D的第一條數(shù)據(jù) db.inventory.delete_many({"status": "A"}) # 刪除符合status值為A的所有數(shù)據(jù)
值得一提的是,刪除操作并不會改變collection的索引設置,即便刪除了這個collection下的所有文檔。
2.5 批量寫入pymongo提供了批量寫入方法:bulk_write(),類似于redis中的pipe_line,它可以將多個寫入操作作為一個list參數(shù)傳入,然后一起執(zhí)行。它支持insert、update、replace、delete的多種方法,以下是官方文檔提供的示例:
try { db.characters.bulkWrite( [ { insertOne : { "document" : { "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4 } } }, { insertOne : { "document" : { "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3 } } }, { updateOne : { "filter" : { "char" : "Eldon" }, "update" : { $set : { "status" : "Critical Injury" } } } }, { deleteOne : { "filter" : { "char" : "Brisbane"} } }, { replaceOne : { "filter" : { "char" : "Meldane" }, "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 } } } ] ); } catch (e) { print(e); }3. 數(shù)據(jù)模型 3.1 基礎知識 3.1.1 靈活的模式
1)同一個集合下,不同文檔的字段可以不一致;同一個集合下,不同文檔的相同字段,類型可以不一致;
2)可以通過對一個文檔的字段進行增刪改操作,或是變更字段類型,來改變文檔的結構。
1) __嵌入式文檔結構__,即在一個文檔內,可以嵌套子文檔內容,實現(xiàn)邏輯相關的數(shù)據(jù)結構嵌套組合。嵌套式文檔結構如下:
# 用戶信息表 { _id: ObjectId_1, username: "youjia", sex: "man", age: 29, contact: { # 嵌入式文檔 phone: 18195181469, email: "jia.you@shunwang.com", } }
2) __引用式__,不同類型數(shù)據(jù)使用id引用進行關聯(lián),上例可變?yōu)椋?/p>
# 用戶表 { _id: ObjectId_1, username: "youjia", sex: "man", age: 29, } # 聯(lián)系信息表(原嵌入式文檔) { _id: ObjectId_2, user_id: ObjectId_1, # 對應用戶表_id phone: 18195181469, email: "jia.you@shunwang.com", }3.1.3 原子性的寫入操作
1) 對一個文檔的寫入操作是原子性的,即使這個寫入操作包含了對嵌套文檔的數(shù)據(jù)寫入。
2) 由于對嵌套文檔的寫入動作是原子性的,因此嵌套式的文檔結構設計,更加促進了寫入操作原子化,提高了寫入效率和數(shù)據(jù)一致性。
3) 當執(zhí)行類似updateMany等操作時,雖然只執(zhí)行了一條指令,但其內部執(zhí)行過程實際上包含了對多個文檔的原子操作。因此這類批量執(zhí)行指令是非原子性的。
4) 由于對多個文檔的批量指令執(zhí)行是非原子性的,因此在對多個文檔進行寫入操作時,寫入任務可能與其他批量寫入任務交叉。
5) 從MongoDB4.0開始,為了保證多文檔寫入/讀取數(shù)據(jù)的一致性,加入了多表操作事務
6) 多表操作事務相比單表操作,會造成大的多的性能消耗,因此官方仍然認為,在多數(shù)情況下 __嵌入式文檔結構是更好的選擇__。
官方提供了多種數(shù)據(jù)模型校驗的方法,包括:1. JSON Schema校驗,2. 查詢表達式校驗。官方推薦使用前者。
一個典型的JSON Schema語法示例:
db.createCollection("students", { validator: { $jsonSchema: { bsonType: "object", required: [ "name", "year", "major", "gpa" ], properties: { name: { bsonType: "string", description: "must be a string and is required" }, gender: { bsonType: "string", description: "must be a string and is not required" }, year: { bsonType: "int", minimum: 2017, maximum: 3017, exclusiveMaximum: false, description: "must be an integer in [ 2017, 3017 ] and is required" }, major: { enum: [ "Math", "English", "Computer Science", "History", null ], description: "can only be one of the enum values and is required" }, gpa: { bsonType: [ "double" ], minimum: 0, description: "must be a double and is required" } } } } })
關于JSON Schema的更詳細信息,可參照網(wǎng)上教程:https://spacetelescope.github...
3.2 模型設計原則 3.2.1 設計原則概述3.1.1中介紹了模型的兩種設計結構:__嵌入式文檔結構__,和 引用式 文檔結構。在設計數(shù)據(jù)模型時,要考慮根據(jù)不同情況選擇適合的文檔結構進行設計。
以下情況下適合使用嵌入式文檔結構:
1) 兩類數(shù)據(jù)是一對一并且具有包含關系。例如:用戶個人信息-用戶聯(lián)系信息
2) 兩類數(shù)據(jù)時一對多關系,但是在應用過程中通常兩類數(shù)據(jù)需要聯(lián)合查詢使用,使用“一”時通常會查詢“多”。
嵌套式文檔結構的優(yōu)點:
嵌套式文檔結構提供了更好的讀性能,數(shù)據(jù)查詢可在一個集合內完成而不必跨集合查詢。
降低了數(shù)據(jù)寫入消耗,數(shù)據(jù)不必多文檔寫入,一次數(shù)據(jù)寫入任務可以在一個文檔內完成,僅執(zhí)行一次原子性操作。
注意:MongoDB默認限制單個文檔大小最大為16MB,因此單個文檔大小不能無限擴大。Mongo提供了其他大體量數(shù)據(jù)的存儲方式:GridFS
以下情況適合使用引用式文檔結構:
1) 當采用嵌套式文檔結構時,被嵌套的數(shù)據(jù)會有大量重復,并且大量重復數(shù)據(jù)造成影響大于嵌套文檔的優(yōu)勢時,選擇引用式文檔結構時更好的選擇。
2) 要設計“多對多”關系時。
3) 為大型分層數(shù)據(jù)集建模時。
引用式文檔的優(yōu)點:
相比嵌套式結構,多組數(shù)據(jù)的關系更加解耦。
更適應多對多的關系場景。
原子性操作數(shù)量是影響數(shù)據(jù)庫操作性能的主要因素之一,多數(shù)情況下,嵌入式文檔結構可以有效降低數(shù)據(jù)庫操作成本,提高性能。
多文檔引用關系下的跨文檔操作,會提高操作成本。
多文檔數(shù)據(jù)操作,涉及到讀寫數(shù)據(jù)一致性問題,需要用到事務(4.0以后版本)。事務的使用會帶來明顯的性能消耗。
對讀操作較多的文檔設置索引可以提升查詢性能,索引設置在查詢較多的字段上,主鍵_id默認設置了索引。
索引對寫操作的性能有影響。
索引會占用一定的數(shù)據(jù)空間,影響內存和磁盤的空間使用。
單個文檔存儲的數(shù)據(jù)量過大時,會影響數(shù)據(jù)庫操作請求往返的時間和帶寬消耗。
單個文檔不要超過16MB,過于小的文檔模型會浪費存儲空間。
小文檔可以通過縮短filed名稱長度來降低存儲空間消耗。
對于沒有持久化需求的數(shù)據(jù),可以設置集合屬性為“限制集合capped collection”來控制集合大小。
4. 索引對于查詢需求較多的文檔,可以通過在適合的字段建立索引來提高查詢效率。但是對文檔建立過多的索引,會影響寫入效率,增加磁盤和內存的空間使用率。
4.1 索引類型 4.1.1 單字段索引對文檔內單個字段建立索引,稱為單字段索引。適合對文檔內單個字段有頻繁查詢請求的場景。
db.person.createIndex( {id_no: 1} )
{id_no: 1}代表升序索引,{id_no: -1}代表降序索引,在單字段索引類型下,升序與降序沒有區(qū)別。
4.1.2 復合索引復合索引是對多個字段聯(lián)合創(chuàng)建一個索引。適合對文檔內某些字段有頻繁查詢請求,以及查詢與排序請求并存的業(yè)務場景。
db.person.createIndex( {age: 1, name: 1} )
創(chuàng)建符合索引時,field的順序是有關系的。索引將按照第一個field進行升序/降序排列,在此基礎上,再對第二個field進行升序/降序排列,以此類推。
4.1.3 多key索引當索引的字段為數(shù)組時,創(chuàng)建出的索引稱為多key索引,多key索引會為數(shù)組的每個元素建立一條索引,比如person表加入一個habbit字段(數(shù)組)用于描述興趣愛好,需要查詢有相同興趣愛好的人就可以利用habbit字段的多key索引。
//文檔格式 {"name" : "jack", "age" : 19, habbit: ["football, runnning"]} // 自動創(chuàng)建多key索引 db.person.createIndex( {habbit: 1} ) db.person.find( {habbit: "football"} )4.2 索引屬性 4.2.1 唯一索引
保證索引對應的字段不會出現(xiàn)相同的值,文檔主鍵_id的索引,就是唯一索引。
4.2.2 TTL索引可以針對某個時間字段,指定文檔的過期時間(經過指定時間后過期 或 在某個時間點過期)
4.2.3 部分索引只針對符合某個特定條件的文檔建立索引,比如某字段值大于5,或者某字段值符合某正則表達式,才建立索引,注意:3.2版本才支持該特性.
4.2.4 稀疏索引只針對存在索引字段的文檔建立索引,可看做是部分索引的一種特殊情況
4.3 索引使用注意事項 4.3.1 創(chuàng)建索引選擇查詢需求較多的文檔創(chuàng)建索引;
文檔中索引創(chuàng)建數(shù)量不宜過多,過多的索引會影響寫入速度,占用磁盤和內存空間。
根據(jù)查詢場景,選擇合適的索引類型。
在已填滿數(shù)據(jù)的集合里創(chuàng)建索引,要設置background選項為True,否則在創(chuàng)建過程中會阻塞所有對該集合的讀寫請求,直至索引創(chuàng)建完成。因此在已有數(shù)據(jù)的集合內創(chuàng)建索引時,要謹慎。
4.3.2 選擇合適的索引
單字段索引
對文檔內的某個字段有頻繁的查詢需求
對文檔內的某個字段有頻繁的排序需求
單字段索引創(chuàng)建,可以不關心索引是升序還是降序的,這對單字段索引沒有影響
可以通過“點標法”對文檔的內嵌文檔中的字段建立索引
復合索引
對文檔內的某些字段有頻繁的查詢需求,并且查詢需求通常是針對多個字段同時進行的
對文檔內的某些字段同時有查詢和排序需求,并且查詢排序需求通常是同時針對多個字段進行的
創(chuàng)建復合索引時,需根據(jù)查詢場景選擇各字段的索引是升序還是降序。例如:
# 創(chuàng)建索引 db.collection.create_index( { "x" : 1, "y" : -1 } ) # 支持下列查詢/排序 db.collection.find().sort( { "x": 1, "y": -1 } ) db.collection.find().sort( { "x": -1, "y": 1 } ) # 對下列查詢/排序,索引不生效 db.collection.find().sort( { "x": 1, "y": 1 } )
根據(jù)業(yè)務場景需求,選擇合適的索引前綴(字段索引順序),后綴的索引是在前綴索引的基礎上建立的。前綴索引可以作為多帶帶的索引字段查詢,但是后綴的索引不可以這樣應用。例如:
# 創(chuàng)建索引 db.collection.create_index( { "x" : 1, "y" : 1 , "z": 1} ) # 支持對下列查詢/排序場景 db.collection.find().sort({"x": 1}) db.collection.find().sort({"x": 1, "y": 1}) db.collection.find().sort({"x": 1, "z": 1}) # 效率較低 db.collection.find().sort({"x": 1, "y": 1, "z": 1}) # 不支持下列查詢/排序場景 db.collection.find().sort({"y": 1}) db.collection.find().sort({"z": 1}) db.collection.find().sort({"y": 1, "z": 1})
多key索引
針對數(shù)組類型的field創(chuàng)建索引,即為多key索引,創(chuàng)建方式與單key索引一樣,當field的數(shù)組元素為內嵌文檔時,可以對內嵌文檔的字段建立多key索引。
一個文檔只允許存在一個多key索引。當此文檔存在多個array類型的field時,只能針對其中一個field建立多key索引。
復合索引中,可以允許一個文檔下存在一個多key索引,而不要求一定是某個field。例如:
# 創(chuàng)建復合索引 db.collection.create_index( { "x" : 1, "y" : 1 } ) # 索引支持的文檔 { "x" : 1, "y" : [1,2,3] } {"x": [1,2,3], "y": 1} # 不支持的情況 {"x": [1,2,3], "y": [1,2,3]}
可以對array內的嵌入式文檔的某個field建立索引。例如:
# 文檔結構 { "x": "test", "y": 1, "z": [ {"a": 1, "b": "test"}, {"a": 2, "b": "some"}, ... ], } # 建立嵌入式文檔的多key索引 db.collection_name.create_index({"z.a": 1, "z.b": -1})
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44763.html
摘要:這個問題應該是百度或者知乎都能知道答案的,以上是自己親身學習的一些途徑方便少走一點彎路入門。 問題1:前端的學習路線 基礎的html,css,js,推薦慕課網(wǎng)免費課程:前端工程師路徑,極客學院免費課程:前端工程師路徑 大概刷過就可以了,不用死記硬背某個知識點,css跟js還需要加深學習的,在實戰(zhàn)過程中不懂就去查文檔 基礎的ps切圖能力 慕課網(wǎng)ps基礎課程 擁有自己的虛擬主機 傳送...
摘要:第一階段基礎階段基礎程序員重點把搞熟練核心是安裝配置基本操作目標能夠完成基本的系統(tǒng)安裝,簡單配置維護能夠做基本的簡單系統(tǒng)的開發(fā)能夠在中型系統(tǒng)中支持某個功能模塊的開發(fā)。本項不做重點學習,除非對前端有興趣。 第一階段:基礎階段(基礎PHP程序員) 重點:把LNMP搞熟練(核心是安裝配置基本操作) 目標:能夠完成基本的LNMP系統(tǒng)安裝,簡單配置維護;能夠做基本的簡單系統(tǒng)的PHP開發(fā);能夠在P...
摘要:使用則需要及以上版本。開發(fā)使用框架七系列教程目錄系列教程大綱快速入門實踐實踐整合整合中和實踐整合中實現(xiàn)緩存中實現(xiàn)通信集成測試及部署實戰(zhàn)圖書管理系統(tǒng) WebFlux 系列教程大綱 一、背景 大家都知道,Spring Framework 是 Java/Spring 應用程序跨平臺開發(fā)框架,也是 Java EE(Java Enterprise Edition) 輕量級框架,其 Spring ...
閱讀 3299·2021-09-30 09:54
閱讀 3782·2021-09-22 15:01
閱讀 3105·2021-08-27 16:19
閱讀 2571·2019-08-29 18:39
閱讀 2145·2019-08-29 14:09
閱讀 622·2019-08-26 10:23
閱讀 1336·2019-08-23 12:01
閱讀 1862·2019-08-22 13:57