Mongodb通配符索引簽名和使用限制問題記錄
學習mongodb,體會mongodb的每一個使用細節(jié),歡迎閱讀威贊的文章。這是威贊發(fā)布的第98篇mongodb技術文章,歡迎瀏覽本專欄威贊發(fā)布的其他文章。如果您認為我的文章對您有幫助或者解決您的問題,歡迎在文章下面點個贊,或者關注威贊。謝謝。威贊文章都是結合官方文檔,翻譯整理而來,并對每個知識點的描述都認真思考和實踐,對難以理解的地方,使用簡單容易理解的方式進行闡述。
Mongodb的通配符索引,為靈活的數(shù)據(jù)結構,提供了便利,但使用上有哪些限制?本文結合Mongodb的官方文檔,總結了Mongodb通配符索引的使用和限制。
索引簽名
自Mongodb5.0開始,通配符索引的wildcardProjection也會被包含到索引簽名當中。索引簽名,是識別索引唯一性的標志,包含了構建索引的各種參數(shù)。將通配符索引的wildcardProjection包含到索引當中,用戶可以建立帶有相同索引鍵但wildcardProjection不同的索引。如為集合books創(chuàng)建兩個通配符索引。
db.books.createIndex({"$**": 1},{
wildcardProjection: {
"author.name": 1,
"author.website": 1
},
name: "authorWildcard"
})
db.books.createIndex({"$**": 1},{
wildcardProjection: {
"publisher.name": 1
},
name: "publisherWildcard"
})查看索引
db.books.getIndexes()
[
{
"v": 2,
"key": {
"_id": 1
},
"name": "_id_"
},
{
"v": 2,
"key": {
"$**": 1
},
"name": "authorWildcard",
"wildcardProjection": {
"author.name": 1,
"author.website": 1
}
},
{
"v": 2,
"key": {
"$**": 1
},
"name": "publisherWildcard",
"wildcardProjection": {
"publisher.name": 1
}
}
]兩個索引都創(chuàng)建成功
通配符索引限制
復合通配符索引限制 一個復合通配符索引只能包含一個通配符表達式,使用下面的表達式構建,是不可以的
{userID: 1, "object1.$**":1, "object2.$**":1}- 復合通配符索引當中,非通配符索引鍵不能使用多鍵索引鍵
- 使用wildcardProjection選項時,構建索引的通配符只能時$**, 不能使用帶有特殊路徑的通配符表達式。下面的表達式是合法的
{
key: { "$**:1"},
name: "index_all_with_projection",
wildcardProjection: {
"someFields.name": 1,
"otherFields.values": 1
}
}而帶有字段的路徑是不合法的
{
key: { "someFields.$**:1"},
name: "index_all_with_projection",
wildcardProjection: {
"someFields.name": 1,
"otherFields.values": 1
}
}_id字段默認沒有包含在通配符索引當中,如果用戶構建的通配符索引需要包含_id字段,使用wildcardProjection指定包含_id字段。
db.studentGrades.createIndex({"$**": 1}, {
wildcardProjection: {
"grades": 1,
"_id": 1
}
})唯一索引和過期時間
添加通配符索引時,不可指定唯一索引或索引過期時間。
空間索引與哈希
不能將通配符索引與空間索引和哈希索引合并創(chuàng)建通配符索引。
分片數(shù)據(jù)集
不能將通配符索引用來分片鍵當中。
通配符索引不支持的查詢
數(shù)組字段不等于空的查詢不支持
如在inventory集合中,字段production_attributes上構建了通配符索引。該通配符索引不支持數(shù)組字段的空值不等查詢。如下面的查詢,Mongodb編排查詢計劃時,不會使用通配符索引
db.inventory.find({$ne: ["product_attributes.tags", null]})
db.inventory.aggregate([
{
$match: { $ne: ["product_attributes.tags", null]}
}
])針對嵌入式文檔和數(shù)組的精確查詢
在構建通配符索引時,Mongodb將嵌入式文檔和數(shù)組進行解析,將解析后的基本數(shù)據(jù)類型和其對應的字段路徑加入到通配符索引當中,而不是將嵌入式文檔和數(shù)組放入到通配符索引的結構當中。因此通配符索引,無法支持基于嵌入式文檔和數(shù)組的精確查詢。如針對inventory集合的查詢,Mongodb在編排查詢計劃時,不會選擇通配符索引。
db.inventory.find(
{
"product_attributes": {"price": 29.99}
}
)
db.inventory.find(
{
"product_attributes.tags": ["waterproof", "fireproof"]
}
)當然,通配符索引也不能夠支持到嵌入式文檔和數(shù)組的不等查詢。
判斷字段是否存在
通配符索引是稀疏的。當通配符索引指定的字段值在文檔當中不存在時,文檔數(shù)據(jù)不會加入到通配符索引當中。因此通配符索引不支持帶有判斷字段是否存在的查詢。
如通配符索引不支持下面的幾個查詢
db.inventory.find(
{
"product_attributes": {$exists: false}
}
)
db.inventory.aggregate([
{
$match: {
"product_attributes": { $exists: false}
}
}
])多字段查詢
MongoDB不能使用非通配符索引來支持查詢謂詞的一部分而使用通配符索引來支持另一部分。
MongoDB不能在同一個查詢中使用多個通配符索引來支持不同的謂詞。
在一個通配符索引可以支持多個查詢字段的情況下,MongoDB只能使用通配符索引來支持其中一個查詢字段。MongoDB會根據(jù)對應的通配符索引路徑自動選擇通配符索引支持的字段。
db.inventory.find(
{
"product_attributes.price": {$gt: 20},
"product_attributes.material": "silk",
"product_attributes.size": "large"
}
)Mongodb通配符索引只能夠支持查詢條件中的一個條件。而選擇哪個條件來使用通配符索引則與通配符索引的路徑有關。
查看上面查詢的執(zhí)行計劃
{
"explainVersion": "2",
"queryPlanner": {
"namespace": "test.inventory",
"indexFilterSet": false,
"parsedQuery": {
"$and": [
{
"product_attributes.material": {
"$eq": "silk"
}
},
{
"product_attributes.size": {
"$eq": "large"
}
},
{
"product_attributes.price": {
"$gt": 20
}
}
]
},
"queryHash": "03951C4C",
"planCacheKey": "BC3202F5",
"maxIndexedOrSolutionsReached": false,
"maxIndexedAndSolutionsReached": false,
"maxScansToExplodeReached": false,
"winningPlan": {
"queryPlan": {
"stage": "FETCH",
"planNodeId": 2,
"filter": {
"$and": [
{
"product_attributes.price": {
"$gt": 20
}
},
{
"product_attributes.size": {
"$eq": "large"
}
}
]
},
"inputStage": {
"stage": "IXSCAN",
"planNodeId": 1,
"keyPattern": {
"$_path": 1,
"product_attributes.material": 1
},
"indexName": "product_attributes.$**_1",
"isMultiKey": false,
"multiKeyPaths": {
"$_path": [],
"product_attributes.material": []
},
"isUnique": false,
"isSparse": true,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"$_path": [
"[\"product_attributes.material\", \"product_attributes.material\"]"
],
"product_attributes.material": [
"[\"silk\", \"silk\"]"
]
}
}
},
"slotBasedPlan": {
"slots": "$$RESULT=s11 env: { s14 = 20, s1 = TimeZoneDatabase(America/Argentina/La_Rioja...Asia/Ashkhabad) (timeZoneDB), s10 = {\"$_path\" : 1, \"product_attributes.material\" : 1}, s6 = KS(3C70726F647563745F617474726962757465732E6D6174657269616C003C73696C6B00FE04), s15 = \"large\", s3 = 1721879566202 (NOW), s2 = Nothing (SEARCH_META), s5 = KS(3C70726F647563745F617474726962757465732E6D6174657269616C003C73696C6B000104) }",
"stages": "[2] filter {(traverseF(s13, lambda(l1.0) { traverseF(getField(l1.0, \"price\"), lambda(l2.0) { ((l2.0 > s14) ?: false) }, false) }, false) && traverseF(s13, lambda(l3.0) { traverseF(getField(l3.0, \"size\"), lambda(l4.0) { ((l4.0 == s15) ?: false) }, false) }, false))} \n[2] nlj inner [] [s4, s7, s8, s9, s10] \n left \n [1] cfilter {(exists(s5) && exists(s6))} \n [1] ixseek s5 s6 s9 s4 s7 s8 [] @\"259baef3-1faf-4703-8a12-870b2c7e1f55\" @\"product_attributes.$**_1\" true \n right \n [2] limit 1 \n [2] seek s4 s11 s12 s7 s8 s9 s10 [s13 = product_attributes] @\"259baef3-1faf-4703-8a12-870b2c7e1f55\" true false \n"
}
},
"rejectedPlans": [
{
"queryPlan": {
"stage": "FETCH",
"planNodeId": 2,
"filter": {
"$and": [
{
"product_attributes.material": {
"$eq": "silk"
}
},
{
"product_attributes.size": {
"$eq": "large"
}
}
]
},
"inputStage": {
"stage": "IXSCAN",
"planNodeId": 1,
"keyPattern": {
"$_path": 1,
"product_attributes.price": 1
},
"indexName": "product_attributes.$**_1",
"isMultiKey": false,
"multiKeyPaths": {
"$_path": [],
"product_attributes.price": []
},
"isUnique": false,
"isSparse": true,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"$_path": [
"[\"product_attributes.price\", \"product_attributes.price\"]"
],
"product_attributes.price": [
"(20, inf.0]"
]
}
}
},
"slotBasedPlan": {
"slots": "$$RESULT=s11 env: { s14 = \"silk\", s10 = {\"$_path\" : 1, \"product_attributes.price\" : 1}, s1 = TimeZoneDatabase(America/Argentina/La_Rioja...Asia/Ashkhabad) (timeZoneDB), s15 = \"large\", s6 = KS(3C70726F647563745F617474726962757465732E70726963650033FFFFFFFFFFFFFFFFFE04), s3 = 1721879566202 (NOW), s5 = KS(3C70726F647563745F617474726962757465732E7072696365002B28FE04), s2 = Nothing (SEARCH_META) }",
"stages": "[2] filter {(traverseF(s13, lambda(l1.0) { traverseF(getField(l1.0, \"material\"), lambda(l2.0) { ((l2.0 == s14) ?: false) }, false) }, false) && traverseF(s13, lambda(l3.0) { traverseF(getField(l3.0, \"size\"), lambda(l4.0) { ((l4.0 == s15) ?: false) }, false) }, false))} \n[2] nlj inner [] [s4, s7, s8, s9, s10] \n left \n [1] cfilter {(exists(s5) && exists(s6))} \n [1] ixseek s5 s6 s9 s4 s7 s8 [] @\"259baef3-1faf-4703-8a12-870b2c7e1f55\" @\"product_attributes.$**_1\" true \n right \n [2] limit 1 \n [2] seek s4 s11 s12 s7 s8 s9 s10 [s13 = product_attributes] @\"259baef3-1faf-4703-8a12-870b2c7e1f55\" true false \n"
}
},
{
"queryPlan": {
"stage": "FETCH",
"planNodeId": 2,
"filter": {
"$and": [
{
"product_attributes.material": {
"$eq": "silk"
}
},
{
"product_attributes.price": {
"$gt": 20
}
}
]
},
"inputStage": {
"stage": "IXSCAN",
"planNodeId": 1,
"keyPattern": {
"$_path": 1,
"product_attributes.size": 1
},
"indexName": "product_attributes.$**_1",
"isMultiKey": false,
"multiKeyPaths": {
"$_path": [],
"product_attributes.size": []
},
"isUnique": false,
"isSparse": true,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"$_path": [
"[\"product_attributes.size\", \"product_attributes.size\"]"
],
"product_attributes.size": [
"[\"large\", \"large\"]"
]
}
}
},
"slotBasedPlan": {
"slots": "$$RESULT=s11 env: { s14 = \"silk\", s10 = {\"$_path\" : 1, \"product_attributes.size\" : 1}, s1 = TimeZoneDatabase(America/Argentina/La_Rioja...Asia/Ashkhabad) (timeZoneDB), s15 = 20, s6 = KS(3C70726F647563745F617474726962757465732E73697A65003C6C6172676500FE04), s3 = 1721879566202 (NOW), s5 = KS(3C70726F647563745F617474726962757465732E73697A65003C6C61726765000104), s2 = Nothing (SEARCH_META) }",
"stages": "[2] filter {(traverseF(s13, lambda(l1.0) { traverseF(getField(l1.0, \"material\"), lambda(l2.0) { ((l2.0 == s14) ?: false) }, false) }, false) && traverseF(s13, lambda(l3.0) { traverseF(getField(l3.0, \"price\"), lambda(l4.0) { ((l4.0 > s15) ?: false) }, false) }, false))} \n[2] nlj inner [] [s4, s7, s8, s9, s10] \n left \n [1] cfilter {(exists(s5) && exists(s6))} \n [1] ixseek s5 s6 s9 s4 s7 s8 [] @\"259baef3-1faf-4703-8a12-870b2c7e1f55\" @\"product_attributes.$**_1\" true \n right \n [2] limit 1 \n [2] seek s4 s11 s12 s7 s8 s9 s10 [s13 = product_attributes] @\"259baef3-1faf-4703-8a12-870b2c7e1f55\" true false \n"
}
}
]
},
"command": {
"find": "inventory",
"filter": {
"product_attributes.price": {
"$gt": 20
},
"product_attributes.material": "silk",
"product_attributes.size": "large"
},
"$db": "test"
},
"serverInfo": {
"host": "TEST-W11",
"port": 27017,
"version": "7.0.4",
"gitVersion": "38f3e37057a43d2e9f41a39142681a76062d582e"
},
"serverParameters": {
"internalQueryFacetBufferSizeBytes": 104857600,
"internalQueryFacetMaxOutputDocSizeBytes": 104857600,
"internalLookupStageIntermediateDocumentMaxSizeBytes": 104857600,
"internalDocumentSourceGroupMaxMemoryBytes": 104857600,
"internalQueryMaxBlockingSortMemoryUsageBytes": 104857600,
"internalQueryProhibitBlockingMergeOnMongoS": 0,
"internalQueryMaxAddToSetBytes": 104857600,
"internalDocumentSourceSetWindowFieldsMaxMemoryBytes": 104857600,
"internalQueryFrameworkControl": "trySbeEngine"
},
"ok": 1
}查詢排序
通配符查詢僅支持索引覆蓋查詢的排序。排序字段還不能是數(shù)組。
如在集合product的product_attributes構建通配符索引
db.products.createIndex({"product_attributes.$**": 1})當price字段不是數(shù)組時,通配符索引可以支持該排序查詢
db.products.find(
{"product_attributes.price": { $gt: 10.00}}
).sort({"product_attributes.price": 1} )到此這篇關于Mongodb通配符索引簽名和使用限制的文章就介紹到這了,更多相關Mongodb索引使用限制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決MongoDB6.0報錯:"mongo"不是內部或外部命令,也不是可運行的程序或批處理文件
這篇文章主要給大家介紹了關于解決MongoDB6.0報錯:"mongo"不是內部或外部命令,也不是可運行的程序或批處理文件的相關資料,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2023-05-05
MongoDB數(shù)據(jù)庫的特色和優(yōu)點介紹
這篇文章主要介紹了MongoDB數(shù)據(jù)庫的特色和優(yōu)點介紹,本文總結了每個開發(fā)人員都應該知道的5個MongoDB特點,需要的朋友可以參考下2015-05-05
Windows系統(tǒng)下安裝Mongodb 3.2.x的步驟詳解
mongodb3.x版本有好多新功能,關于這方面參考官網即可,下面這篇文章主要給大家介紹了在Windows系統(tǒng)下安裝Mongodb 3.2.x的詳細步驟,文中介紹的非常詳細,需要的朋友們可以參考學習,下面來一起看看吧。2017-03-03
MongoDB系列教程(三):Windows中下載和安裝MongoDB
這篇文章主要介紹了MongoDB系列教程(三):MongoDB下載和安裝,本文講解使用Windows環(huán)境安裝MongoDB,需要的朋友可以參考下2015-05-05
MongoDB數(shù)據(jù)去重與保存最新數(shù)據(jù)操作指南
在 MongoDB 數(shù)據(jù)庫中,我們經常需要進行數(shù)據(jù)去重并保留最新的數(shù)據(jù),本文將介紹如何使用 MongoDB 聚合操作完成這一任務,并將結果保存到新的集合或者覆蓋原有的集合,感興趣的小伙伴跟著小編一起來看看吧2024-01-01

