前一篇簡(jiǎn)單介紹了索引,并給出了基本的索引使用,這一次,我們進(jìn)一步說(shuō)一下MongoDB中的索引,包括如何查看查詢是否走索引,如何管理索引和地理空間索引等。
【使用explain和hint】
前面講高級(jí)查詢選項(xiàng)時(shí),提到過(guò)"$explain" 和 ”$hint“可以作為包裝查詢的選項(xiàng)關(guān)鍵字使用,其實(shí)這兩個(gè)本身就可以作為操作游標(biāo)的函數(shù)調(diào)用!游標(biāo)調(diào)用explain函數(shù)會(huì)返回一個(gè)文檔,用于描述當(dāng)前查詢的一些細(xì)節(jié)信息。這也不同于我們前面介紹的游標(biāo)函數(shù),前面提到的游標(biāo)處理函數(shù)都是返回游標(biāo),可組成方法鏈調(diào)用。我們看一下explain的具體應(yīng)用
>?db.blogs.findOne();?? {?? ????????"_id" ?:?ObjectId( "502262ab09248743250688ea" ),?? ????????"content" ?:? "....." ,?? ????????"comment" ?:?[?? ????????????????{?? ????????????????????????"author" ?:? "joe" ,?? ????????????????????????"score" ?:?3,?? ????????????????????????"comment" ?:? "just?so?so!" ?? ????????????????},?? ????????????????{?? ????????????????????????"author" ?:? "jimmy" ,?? ????????????????????????"score" ?:?5,?? ????????????????????????"comment" ?:? "cool!?good!" ?? ????????????????}?? ????????]?? }?? >?db.blogs.find({"comment.author" : "joe" }).explain();?? {?? ????????"cursor" ?:? "BtreeCursor?comment.author_1" ,?? ????????"nscanned" ?:?1,?? ????????"nscannedObjects" ?:?1,?? ????????"n" ?:?1,?? ????????"millis" ?:?70,?? ????????"nYields" ?:?0,?? ????????"nChunkSkips" ?:?0,?? ????????"isMultiKey" ?:? true ,?? ????????"indexOnly" ?:? false ,?? ????????"indexBounds" ?:?{?? ????????????????"comment.author" ?:?[?? ????????????????????????[?? ????????????????????????????????"joe" ,?? ????????????????????????????????"joe" ?? ????????????????????????]?? ????????????????]?? ????????}?? } ?
我們?cè)诩蟗logs上為內(nèi)嵌文檔的鍵“comment.author”建立了索引,然后我們使用這個(gè)鍵作為查詢條件查詢文檔,在游標(biāo)上調(diào)用explain返回上述文檔,我們解釋一下返回文檔幾個(gè)主要鍵的含義:
1》 “cursor”:因?yàn)檫@個(gè)查詢使用了索引,MongoDB中索引存儲(chǔ)在B樹(shù)結(jié)構(gòu)中,所以這是也使用了BtreeCursor類型的游標(biāo)。如果沒(méi)有使用索引,游標(biāo)的類型是BasicCursor。這個(gè)鍵還會(huì)給出你所使用的索引的名稱,你通過(guò)這個(gè)名稱可以查看當(dāng)前數(shù)據(jù)庫(kù)下的system.indexes集合(系統(tǒng)自動(dòng)創(chuàng)建,由于存儲(chǔ)索引信息,這個(gè)稍微會(huì)提到)來(lái)得到索引的詳細(xì)信息。
2》 “nscanned”/“nscannedObjects ”:表明當(dāng)前這次查詢一共掃描了集合中多少個(gè)文檔,我們的目的是,讓這個(gè)數(shù)值和返回文檔的數(shù)量越接近越好。
3》 "n":當(dāng)前查詢返回的文檔數(shù)量。
4》 “millis”:當(dāng)前查詢所需時(shí)間,毫秒數(shù)。
5》 “indexBounds”:當(dāng)前查詢具體使用的索引
上述我們的文檔只是定義了一個(gè)內(nèi)嵌文檔的索引,我們查詢也正好使用了這個(gè)鍵,這個(gè)情況比較簡(jiǎn)單。我們?cè)倏匆粋€(gè)稍微復(fù)雜些的情況!集合user上有兩個(gè)索引{"name":1,“age”:1}和{“age”:1,“name”:1},我們按照這兩個(gè)鍵查詢,再看看explain的返回:
[javascript] ?view plain
?copy >?db.user.ensureIndex({ "name" :1, "age" :1});?? >?db.user.ensureIndex({"age" :1, "name" :1});?? >?db.user.find({"age" :40,? "name" : "tim" }).explain();?? {?? ????????"cursor" ?:? "BtreeCursor?name_1_age_1" ,?? ????????"nscanned" ?:?1,?? ????????"nscannedObjects" ?:?1,?? ????????"n" ?:?1,?? ????????"millis" ?:?0,?? ????????"nYields" ?:?0,?? ????????"nChunkSkips" ?:?0,?? ????????"isMultiKey" ?:? false ,?? ????????"indexOnly" ?:? false ,?? ????????"indexBounds" ?:?{?? ????????????????"name" ?:?[?? ????????????????????????[?? ????????????????????????????????"tim" ,?? ????????????????????????????????"tim" ?? ????????????????????????]?? ????????????????],?? ????????????????"age" ?:?[?? ????????????????????????[?? ????????????????????????????????40,?? ????????????????????????????????40?? ????????????????????????]?? ????????????????]?? ????????}?? }?? >??
我們看,返回文檔的鍵沒(méi)有區(qū)別,其默認(rèn)使用了索引"name_1_age_1",這是查詢優(yōu)化器為我們使用的索引!我們此處可以通過(guò)hint進(jìn)行更行,即強(qiáng)制這個(gè)查詢使用我們定義的“age_1_name_1”索引,如下:
[javascript] ?view plain
?copy >? var ?cursor?=?db.user.find({ "age" :40,? "name" : "tim" }).hint({ "age" :1, "name" :1});?? >?cursor.explain();?? {?? ????????"cursor" ?:? "BtreeCursor?age_1_name_1" ,?? ????????"nscanned" ?:?1,?? ????????"nscannedObjects" ?:?1,?? ????????"n" ?:?1,?? ????????"millis" ?:?0,?? ????????"nYields" ?:?0,?? ????????"nChunkSkips" ?:?0,?? ????????"isMultiKey" ?:? false ,?? ????????"indexOnly" ?:? false ,?? ????????"indexBounds" ?:?{?? ????????????????"age" ?:?[?? ????????????????????????[?? ????????????????????????????????40,?? ????????????????????????????????40?? ????????????????????????]?? ????????????????],?? ????????????????"name" ?:?[?? ????????????????????????[?? ????????????????????????????????"tim" ,?? ????????????????????????????????"tim" ?? ????????????????????????]?? ????????????????]?? ????????}?? }?? >??
我們看,hint函數(shù)不同于explain函數(shù),會(huì)返回游標(biāo),我們可以在游標(biāo)上調(diào)用explain查看索引的使用情況!99%的情況,我們沒(méi)有必要通過(guò)hint去強(qiáng)制使用某個(gè)索引,MongoDB的查詢優(yōu)化器非常智能,絕對(duì)能幫助我們使用最佳的索引去進(jìn)行查詢!
【索引管理】
上面提到索引的元信息(描述信息)存儲(chǔ)在集合system.indexes中,這是系統(tǒng)提供的保留集合(創(chuàng)建數(shù)據(jù)庫(kù)時(shí)),我們不能對(duì)其進(jìn)行插入或刪除操作!我們可以從中查看索引定義的相關(guān)信息,我們操作這個(gè)集合只能通過(guò)ensureIndex(插入索引),dropIndex(刪除索引)兩個(gè)函數(shù)!我們先看看system.indexes這個(gè)集合吧:
[javascript] ?view plain
?copy >?db.system.indexes.find();?? {?"v" ?:?1,? "key" ?:?{? "_id" ?:?1?},? "ns" ?:? "mylearndb.blogs" ,? "name" ?:? "_id_" ?}?? {?"v" ?:?1,? "key" ?:?{? "_id" ?:?1?},? "ns" ?:? "mylearndb.people" ,? "name" ?:? "_id_" ?}?? {?"v" ?:?1,? "key" ?:?{? "_id" ?:?1?},? "ns" ?:? "mylearndb.users" ,? "name" ?:? "_id_" ?}??
系統(tǒng)會(huì)默認(rèn)為集合創(chuàng)建"_id"唯一性索引,所以這個(gè)表會(huì)有很多這種“name”為“_id_”的索引信息。鍵“ns”是“數(shù)據(jù)庫(kù)名.集合名”,我們可以通過(guò)這個(gè)查詢一個(gè)集合上定義的所有索引:
[javascript] ?view plain
?copy >?db.system.indexes.find({ "ns" : "mylearndb.user" });?? {?"v" ?:?1,? "key" ?:?{? "_id" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:? "_id_" ?}?? {?"v" ?:?1,? "key" ?:?{? "name" ?:?1?},? "unique" ?:? true ,? "ns" ?:? "mylearndb.user" ,? "name" ?:? "name_1" ,? "dropDups" ?:? true ?}?? {?"v" ?:?1,? "key" ?:?{? "name" ?:?1,? "age" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:? "name_1_age_1" ?}?? {?"v" ?:?1,? "key" ?:?{? "age" ?:?1,? "name" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:? "age_1_name_1" ?}?? >??
我們也可通過(guò)鍵"name”來(lái)查詢特定索引的元信息,這里不做演示了。
【修改索引】
隨著應(yīng)用數(shù)據(jù)的積累或集合結(jié)構(gòu)的改變,老的索引會(huì)出現(xiàn)效率低下的問(wèn)題,修改索引頁(yè)也是不可避免了。我們可以隨時(shí)通過(guò)ensureIndex函數(shù)為集合添加索引,這個(gè)函數(shù)前面已經(jīng)多次使用,這里我們?cè)俳榻B該函數(shù)第二個(gè)參數(shù)文檔的一個(gè)鍵"background",布爾類型,表明是否在數(shù)據(jù)庫(kù)服務(wù)空閑時(shí)來(lái)構(gòu)建索引,因?yàn)樗饕臉?gòu)建是一個(gè)耗時(shí)耗資源的過(guò)程,并且在構(gòu)建過(guò)程中,數(shù)據(jù)庫(kù)會(huì)阻塞所有的訪問(wèn)請(qǐng)求,對(duì)于一個(gè)大數(shù)量的集合添加索引我們應(yīng)該啟用這個(gè)選型!我們還要知道的是,即時(shí)啟用了這個(gè)選項(xiàng),構(gòu)建仍會(huì)影響正常服務(wù),但不會(huì)徹底阻塞數(shù)據(jù)庫(kù)服務(wù):
[javascript] ?view plain
?copy >?db.user.ensureIndex({ "name" :1, "registered" :-1},{ "background" : true });?? >??
其使用方式和以前創(chuàng)建索引的過(guò)程沒(méi)有區(qū)別。
對(duì)于沒(méi)有用的索引,我們應(yīng)盡快刪除,因?yàn)樗饕龝?huì)影響數(shù)據(jù)庫(kù)的增刪改的效率!利用集合的dropIndex(indexName)刪除一個(gè)集合上的特定索引。我們使用這個(gè)函數(shù)的正確步驟應(yīng)該是先通過(guò)查詢system.indexes確認(rèn)索引的名稱,然后再刪除,這樣做是因?yàn)椴皇撬姓Z(yǔ)言的數(shù)據(jù)庫(kù)驅(qū)動(dòng)都是按照我們前面介紹的方式去生成索引名稱:
[javascript] ?view plain
?copy >?db.system.indexes.find({ "ns" : "mylearndb.user" });?? {?"v" ?:?1,? "key" ?:?{? "_id" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:? "_id_" ?}?? {?"v" ?:?1,? "key" ?:?{? "name" ?:?1,? "age" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:?? {?"v" ?:?1,? "key" ?:?{? "age" ?:?1,? "name" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:?? >?db.user.dropIndex("name_1_age_1" );?? {?"nIndexesWas" ?:?3,? "ok" ?:?1?}?? >?db.system.indexes.find({"ns" : "mylearndb.user" });?? {?"v" ?:?1,? "key" ?:?{? "_id" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:? "_id_" ?}?? {?"v" ?:?1,? "key" ?:?{? "age" ?:?1,? "name" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:?? >??
我們需要注意,集合還有一個(gè)函數(shù)dropIndexes,不接受任何參數(shù),這個(gè)函數(shù)要慎用啊,他會(huì)直接將集合所有的索引全部刪掉!Shell中還可以通過(guò)運(yùn)行命令的方式刪除一個(gè)索引:
[javascript] ?view plain
?copy >?db.system.indexes.find({ "ns" : "mylearndb.user" });?? {?"v" ?:?1,? "key" ?:?{? "_id" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:? "_id_" ?}?? {?"v" ?:?1,? "key" ?:?{? "age" ?:?1,? "name" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:? "age_1_name_1" ?}?? >?db.runCommand({"dropIndexes" : "user" , "index" : "age_1_name_1" });?? {?"nIndexesWas" ?:?2,? "ok" ?:?1?}?? >?db.system.indexes.find({"ns" : "mylearndb.user" });?? {?"v" ?:?1,? "key" ?:?{? "_id" ?:?1?},? "ns" ?:? "mylearndb.user" ,? "name" ?:? "_id_" ?}?? >??
從上述的例子可看到這個(gè)命令的使用情況,其中鍵"dropIndexes"指明要?jiǎng)h除索引所在的集合,鍵"index"指明要?jiǎng)h除的索引的名稱!如果這里名稱指明為一個(gè)“*”,則表明是刪除集合上所有的索引!
除此之外,還有一種刪除索引的方式是將集合刪掉,這樣所有索引(包括鍵“_id”的唯一索引)、文檔都會(huì)被刪除。上述的刪除所有索引的方式都不會(huì)刪除系統(tǒng)為鍵“_id”創(chuàng)建的唯一索引。調(diào)用集合的remove函數(shù),即使刪除所有文檔,也不會(huì)刪除索引,當(dāng)你往集合中添加數(shù)據(jù)時(shí),該索引還會(huì)起作用。
MongoDB中,往含有數(shù)據(jù)的集合上添加索引比向空集合添加索引后插入數(shù)據(jù)要快一些,這個(gè)在進(jìn)行數(shù)據(jù)庫(kù)數(shù)據(jù)初始化時(shí)可以考慮一下。
【地理空間索引】
目前網(wǎng)絡(luò)上LBS(location based service)越來(lái)越流行,有一個(gè)應(yīng)用就是查詢你所在位置附件的某些場(chǎng)所。為了提升這種查詢的速度(查詢不同于上面單維度,需要搜索兩個(gè)維度),MongoDB為坐標(biāo)平面查詢提供了專門的索引,即稱作地理空間索引。
由于建立地理空間索引的鍵的值必須是一對(duì)值:一個(gè)包含兩個(gè)數(shù)值的數(shù)組或包含兩個(gè)鍵的內(nèi)嵌文檔(內(nèi)嵌文檔的鍵的名稱無(wú)所謂),如:{“gps”:[123,134]},{“gps”:{“x”:123,“y”:134}},{“gps”:{“l(fā)atitude”:123,“l(fā)ongitude”:134}}。這些文檔的鍵“gps”,我們都可以再上面建立地理空間索引:
[javascript] ?view plain
?copy >?db.shopstreet.find();?? {?"_id" ?:?ObjectId( "502673678a84caa12e8070be" ),? "desc" ?:? "coffeehouse" ,? "gps" ?:?[?100,?120?]?}?? {?"_id" ?:?ObjectId( "502673738a84caa12e8070bf" ),? "desc" ?:? "coffeebar" ,? "gps" ?:?[?110,?130?]?}?? {?"_id" ?:?ObjectId( "502673838a84caa12e8070c0" ),? "desc" ?:? "coffee?king" ,? "gps" ?:?[?110,?123?]?}?? {?"_id" ?:?ObjectId( "502673a08a84caa12e8070c1" ),? "desc" ?:? "coffee?buck" ,? "gps" ?:?[?106,?113?]?}?? {?"_id" ?:?ObjectId( "502674028a84caa12e8070c2" ),? "desc" ?:? "nike?shop" ,? "gps" ?:?[?109,?111?]?}?? >?db.shopstreet.ensureIndex({"gps" ?:? "2d" });?? >??
建立地理空間索引同樣調(diào)用ensureIndex方法,{"gps" : "2d"},以前建立索引鍵的值為1,或-1,地理空間索引的值固定為"2d"。地理空間索引默認(rèn)值的范圍為(-180~180)(對(duì)于經(jīng)緯度很適合),但我們?cè)趧?chuàng)建索引時(shí)可以指定其值的范圍:
[javascript] ?view plain
?copy >?db.shopstreet.ensureIndex({ "gps" ?:? "2d" },{ "min" :-1000, "max" :1000});?? >??
上面我們創(chuàng)建的地理空間索引值的范圍為-1000~1000。
地理空間查詢可以通過(guò)find或使用數(shù)據(jù)庫(kù)命令。這里我們需要使用“$near”查詢操作符,如下:
[javascript] ?view plain
?copy >?db.shopstreet.find({ "gps" :{ "$near" ?:?[110,130]}});?? {?"_id" ?:?ObjectId( "502673738a84caa12e8070bf" ),? "desc" ?:? "coffeebar" ,? "gps" ?:?[?110,?130?]?}?? {?"_id" ?:?ObjectId( "502673838a84caa12e8070c0" ),? "desc" ?:? "coffee?king" ,? "gps" ?:?[?110,?123?]?}?? {?"_id" ?:?ObjectId( "502673678a84caa12e8070be" ),? "desc" ?:? "coffeehouse" ,? "gps" ?:?[?100,?120?]?}?? {?"_id" ?:?ObjectId( "502673a08a84caa12e8070c1" ),? "desc" ?:? "coffee?buck" ,? "gps" ?:?[?106,?113?]?}?? {?"_id" ?:?ObjectId( "502674028a84caa12e8070c2" ),? "desc" ?:? "nike?shop" ,? "gps" ?:?[?109,?111?]?}?? >??
這個(gè)查詢會(huì)按點(diǎn)(110,130)來(lái)查詢文檔,由遠(yuǎn)及近將符合條件的文檔返回,如果沒(méi)有在游標(biāo)上使用limit函數(shù),默認(rèn)會(huì)返回100條文檔。通常我們會(huì)利用limit限制前幾個(gè)最靠近的目標(biāo)文檔即可!我們可以使用數(shù)據(jù)庫(kù)命令完成上述查詢:
[javascript] ?view plain
?copy >?db.shopstreet.ensureIndex({ "gps" ?:? "2d" },{ "min" :-1000, "max" :1000});?? >?db.shopstreet.find({"gps" :{ "$near" ?:?[110,130]}});?? {?"_id" ?:?ObjectId( "502673738a84caa12e8070bf" ),? "desc" ?:? "coffeebar" ,? "gps" ?:?[?110,?130?]?}?? {?"_id" ?:?ObjectId( "502673838a84caa12e8070c0" ),? "desc" ?:? "coffee?king" ,? "gps" ?:?[?110,?123?]?}?? {?"_id" ?:?ObjectId( "502673678a84caa12e8070be" ),? "desc" ?:? "coffeehouse" ,? "gps" ?:?[?100,?120?]?}?? {?"_id" ?:?ObjectId( "502673a08a84caa12e8070c1" ),? "desc" ?:? "coffee?buck" ,? "gps" ?:?[?106,?113?]?}?? {?"_id" ?:?ObjectId( "502674028a84caa12e8070c2" ),? "desc" ?:? "nike?shop" ,? "gps" ?:?[?109,?111?]?}?? >?db.runCommand({"geoNear" : "shopstreet" ,? "near" :[110,130],? "num" :3});?? {?? ????????"ns" ?:? "mylearndb.shopstreet" ,?? ????????"near" ?:? "1111000111111000000111111000000111111000000111111000" ,?? ????????"results" ?:?[?? ????????????????{?? ????????????????????????"dis" ?:?0,?? ????????????????????????"obj" ?:?{?? ????????????????????????????????"_id" ?:?ObjectId( "502673738a84caa12e8070bf" ),?? ????????????????????????????????"desc" ?:? "coffeebar" ,?? ????????????????????????????????"gps" ?:?[?? ????????????????????????????????????????110,?? ????????????????????????????????????????130?? ????????????????????????????????]?? ????????????????????????}?? ????????????????},?? ????????????????{?? ????????????????????????"dis" ?:?7,?? ????????????????????????"obj" ?:?{?? ????????????????????????????????"_id" ?:?ObjectId( "502673838a84caa12e8070c0" ),?? ????????????????????????????????"desc" ?:? "coffee?king" ,?? ????????????????????????????????"gps" ?:?[?? ????????????????????????????????????????110,?? ????????????????????????????????????????123?? ????????????????????????????????]?? ????????????????????????}?? ????????????????},?? ????????????????{?? ????????????????????????"dis" ?:?14.142135623730951,?? ????????????????????????"obj" ?:?{?? ????????????????????????????????"_id" ?:?ObjectId( "502673678a84caa12e8070be" ),?? ????????????????????????????????"desc" ?:? "coffeehouse" ,?? ????????????????????????????????"gps" ?:?[?? ????????????????????????????????????????100,?? ????????????????????????????????????????120?? ????????????????????????????????]?? ????????????????????????}?? ????????????????}?? ????????],?? ????????"stats" ?:?{?? ????????????????"time" ?:?0,?? ????????????????"btreelocs" ?:?0,?? ????????????????"nscanned" ?:?5,?? ????????????????"objectsLoaded" ?:?4,?? ????????????????"avgDistance" ?:?7.04737854124365,?? ????????????????"maxDistance" ?:?14.142152482638018?? ????????},?? ????????"ok" ?:?1?? }?? >??
這個(gè)命令接受一個(gè)文檔,文檔中鍵"geoNear"指明查詢的集合,鍵"near"指明查詢的基準(zhǔn)坐標(biāo)值,鍵"num"指定返回的結(jié)果數(shù)量!然后執(zhí)行后返回如上結(jié)果,這個(gè)命令同時(shí)還會(huì)返回每個(gè)返回文檔距查詢點(diǎn)的距離,這個(gè)距離的數(shù)據(jù)單位就是你數(shù)據(jù)的單位,如上述數(shù)據(jù)位經(jīng)緯度,鍵“dis”后面的距離數(shù)值就是經(jīng)緯度!
MongoDB不但能找到靠近一個(gè)點(diǎn)的文檔,還能找到指定形狀內(nèi)的文檔!使用查詢操作符"$within"即可,同時(shí)通過(guò)MongoDB提供的查詢操作符指定形狀,如“$box”可以指定矩形,“$center”可以指定圓形:
[javascript] ?view plain
?copy >?db.shopstreet.find();?? {?"_id" ?:?ObjectId( "502673678a84caa12e8070be" ),? "desc" ?:? "coffeehouse" ,? "gps" ?:?[?100,?120?]?}?? {?"_id" ?:?ObjectId( "502673738a84caa12e8070bf" ),? "desc" ?:? "coffeebar" ,? "gps" ?:?[?110,?130?]?}?? {?"_id" ?:?ObjectId( "502673838a84caa12e8070c0" ),? "desc" ?:? "coffee?king" ,? "gps" ?:?[?110,?123?]?}?? {?"_id" ?:?ObjectId( "502673a08a84caa12e8070c1" ),? "desc" ?:? "coffee?buck" ,? "gps" ?:?[?106,?113?]?}?? {?"_id" ?:?ObjectId( "502674028a84caa12e8070c2" ),? "desc" ?:? "nike?shop" ,? "gps" ?:?[?109,?111?]?}?? >?db.shopstreet.find({"gps" ?:?{ "$within" ?:?{ "$box" :[[109,130],[110,120]]}}});?? {?"_id" ?:?ObjectId( "502673838a84caa12e8070c0" ),? "desc" ?:? "coffee?king" ,? "gps" ?:?[?110,?123?]?}?? {?"_id" ?:?ObjectId( "502673738a84caa12e8070bf" ),? "desc" ?:? "coffeebar" ,? "gps" ?:?[?110,?130?]?}??
?通過(guò){"$box":[[109,130],[110,120]]}指定一個(gè)矩形,其左下角和右上角坐標(biāo)!“$within”指定查詢?cè)谶@個(gè)范圍內(nèi)的點(diǎn)。
[javascript] ?view plain
?copy >?db.shopstreet.find();?? {?"_id" ?:?ObjectId( "502673678a84caa12e8070be" ),? "desc" ?:? "coffeehouse" ,? "gps" ?:?[?100,?120?]?}?? {?"_id" ?:?ObjectId( "502673738a84caa12e8070bf" ),? "desc" ?:? "coffeebar" ,? "gps" ?:?[?110,?130?]?}?? {?"_id" ?:?ObjectId( "502673838a84caa12e8070c0" ),? "desc" ?:? "coffee?king" ,? "gps" ?:?[?110,?123?]?}?? {?"_id" ?:?ObjectId( "502673a08a84caa12e8070c1" ),? "desc" ?:? "coffee?buck" ,? "gps" ?:?[?106,?113?]?}?? {?"_id" ?:?ObjectId( "502674028a84caa12e8070c2" ),? "desc" ?:? "nike?shop" ,? "gps" ?:?[?109,?111?]?}?? >?db.shopstreet.find({"gps" ?:?{ "$within" ?:?{ "$center" :[[110,130],10]}}});?? {?"_id" ?:?ObjectId( "502673838a84caa12e8070c0" ),? "desc" ?:? "coffee?king" ,? "gps" ?:?[?110,?123?]?}?? {?"_id" ?:?ObjectId( "502673738a84caa12e8070bf" ),? "desc" ?:? "coffeebar" ,? "gps" ?:?[?110,?130?]?}?? >??
上述是通過(guò)指定一個(gè)圓形來(lái)查詢同樣的點(diǎn),{"$center":[[110,130],10]},指定了圓形的圓心坐標(biāo)和半徑!
【復(fù)合地理空間索引】
通常我們查找一個(gè)位置,不會(huì)只是通過(guò)坐標(biāo)去定位,還會(huì)添加其他條件,我們構(gòu)建索引時(shí)也可以用上:
[javascript] ?view plain
?copy >?db.shopstreet.find();?? {?"_id" ?:?ObjectId( "502673678a84caa12e8070be" ),? "desc" ?:? "coffeehouse" ,? "gps" ?:?[?100,?120?]?}?? {?"_id" ?:?ObjectId( "502673738a84caa12e8070bf" ),? "desc" ?:? "coffeebar" ,? "gps" ?:?[?110,?130?]?}?? {?"_id" ?:?ObjectId( "502673838a84caa12e8070c0" ),? "desc" ?:? "coffee?king" ,? "gps" ?:?[?110,?123?]?}?? {?"_id" ?:?ObjectId( "502673a08a84caa12e8070c1" ),? "desc" ?:? "coffee?buck" ,? "gps" ?:?[?106,?113?]?}?? {?"_id" ?:?ObjectId( "502674028a84caa12e8070c2" ),? "desc" ?:? "nike?shop" ,? "gps" ?:?[?109,?111?]?}?? >?db.showstreet.ensureIndex({"gps" : "2d" ,? "desc" :1});?? >??
上述就創(chuàng)建了一個(gè)復(fù)合地理空間索引,這個(gè)索引更符合實(shí)際需要!
上述就是MongoDB中索引的使用,索引是數(shù)據(jù)庫(kù)查詢提升效率的利器,對(duì)于任何數(shù)據(jù)庫(kù)都是如此!我們應(yīng)該好好掌握!
總結(jié)
以上是生活随笔 為你收集整理的查看MongoDB索引的使用,管理索引 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。