摘要:下面列出了使用作為文件存儲(chǔ)的理由。如果已經(jīng)在使用,那么可以使用來(lái)代替獨(dú)立的文件存儲(chǔ)工具。在中,文件存儲(chǔ)的集中度會(huì)比較高,因?yàn)槭且詾閱挝粊?lái)分配數(shù)據(jù)文件的。揭開(kāi)的面紗是一種輕量級(jí)的文件存儲(chǔ)規(guī)范,用于存儲(chǔ)中的普通文檔。
上一篇文章:MongoDB指南---14、特殊的索引和集合:固定集合、TTL索引、全文本索引地理空間索引
下一篇文章:MongoDB指南---16、聚合
MongoDB支持幾種類型的地理空間索引。其中最常用的是2dsphere索引(用于地球表面類型的地圖)和2d索引(用于平面地圖和時(shí)間連續(xù)的數(shù)據(jù))。
2dsphere允許使用GeoJSON格式(http://www.geojson.org)指定點(diǎn)、線和多邊形。點(diǎn)可以用形如[longitude, latitude]([經(jīng)度,緯度])的兩個(gè)元素的數(shù)組表示:
{ "name" : "New York City", "loc" : { "type" : "Point", "coordinates" : [50, 2] } }
線可以用一個(gè)由點(diǎn)組成的數(shù)組來(lái)表示:
{ "name" : "Hudson River", "loc" : { "type" : "Line", "coordinates" : [[0,1], [0,2], [1,2]] } }
多邊形的表示方式與線一樣(都是一個(gè)由點(diǎn)組成的數(shù)組),但是"type"不同:
{ "name" : "New England", "loc" : { "type" : "Polygon", "coordinates" : [[0,1], [0,2], [1,2]] } }
"loc"字段的名字可以是任意的,但是其中的子對(duì)象是由GeoJSON指定的,不能改變。
在ensureIndex中使用"2dsphere"選項(xiàng)就可以創(chuàng)建一個(gè)地理空間索引:
> db.world.ensureIndex({"loc" : "2dsphere"})地理空間查詢的類型
可以使用多種不同類型的地理空間查詢:交集(intersection)、包含(within)以及接近(nearness)。查詢時(shí),需要將希望查找的內(nèi)容指定為形如{"$geometry" : geoJsonDesc}的GeoJSON對(duì)象。
例如,可以使用"$geoIntersects"操作符找出與查詢位置相交的文檔:
> var eastVillage = { ... "type" : "Polygon", ... "coordinates" : [ ... [-73.9917900, 40.7264100], ... [-73.9917900, 40.7321400], ... [-73.9829300, 40.7321400], ... [-73.9829300, 40.7264100] ... ]} > db.open.street.map.find( ... {"loc" : {"$geoIntersects" : {"$geometry" : eastVillage}}})
這樣就會(huì)找到所有與East Village區(qū)域有交集的文檔。
可以使用"$within"查詢完全包含在某個(gè)區(qū)域的文檔,例如:“East Village有哪些餐館?”
> db.open.street.map.find({"loc" : {"$within" : {"$geometry" : eastVillage}}})
與第一個(gè)查詢不同,這次不會(huì)返回那些只是經(jīng)過(guò)East Village(比如街道)或者部分重疊(比如用于表示曼哈頓的多邊形)的文檔。
最后,可以使用"$near"查詢附近的位置:
> db.open.street.map.find({"loc" : {"$near" : {"$geometry" : eastVillage}}})
注意,"$near"是唯一一個(gè)會(huì)對(duì)查詢結(jié)果進(jìn)行自動(dòng)排序的地理空間操作符:"$near"的返回結(jié)果是按照距離由近及遠(yuǎn)排序的。
地理位置查詢有一點(diǎn)非常有趣:不需要地理空間索引就可以使用"$geoIntersects"或者"$within"("$near"需要使用索引)。但是,建議在用于表示地理位置的字段上建立地理空間索引,這樣可以顯著提高查詢速度。
如果有其他類型的索引,可以將地理空間索引與其他字段組合在一起使用,以便對(duì)更復(fù)雜的查詢進(jìn)行優(yōu)化。上面提到過(guò)一種可能的查詢:“East Village有哪些餐館?”。如果僅僅使用地理空間索引,我們只能查找到East Village內(nèi)的所有東西,但是如果要將“restaurants”或者是“pizza”多帶帶查詢出來(lái),就需要使用其他索引中的字段了:
> db.open.street.map.ensureIndex({"tags" : 1, "location" : "2dsphere"})
然后就能夠很快地找到East Village內(nèi)的披薩店了:
> db.open.street.map.find({"loc" : {"$within" : {"$geometry" : eastVillage}}, ... "tags" : "pizza"})
其他索引字段可以放在"2dsphere"字段前面也可以放在后面,這取決于我們希望首先使用其他索引的字段進(jìn)行過(guò)濾還是首先使用位置進(jìn)行過(guò)濾。應(yīng)該將那個(gè)能夠過(guò)濾掉盡可能多的結(jié)果的字段放在前面。
2D索引對(duì)于非球面地圖(游戲地圖、時(shí)間連續(xù)的數(shù)據(jù)等),可以使用"2d"索引代替"2dsphere":
> db.hyrule.ensureIndex({"tile" : "2d"})
"2d"索引用于扁平表面,而不是球體表面。"2d"索引不應(yīng)該用在球體表面上,否則極點(diǎn)附近會(huì)出現(xiàn)大量的扭曲變形。
文檔中應(yīng)該使用包含兩個(gè)元素的數(shù)組表示2d索引字段(寫作本書時(shí),這個(gè)字段還不是GeoJSON文檔)。示例如下:
{ "name" : "Water Temple", "tile" : [ 32, 22 ] }
"2d"索引只能對(duì)點(diǎn)進(jìn)行索引。可以保存一個(gè)由點(diǎn)組成的數(shù)組,但是它只會(huì)被保存為由點(diǎn)組成的數(shù)組,不會(huì)被當(dāng)成線。特別是對(duì)于"$within"查詢來(lái)說(shuō),這是一項(xiàng)重要的區(qū)別。如果將街道保存為由點(diǎn)組成的數(shù)組,那么如果其中的某個(gè)點(diǎn)位于給定的形狀之內(nèi),這個(gè)文檔就會(huì)與$within相匹配。但是,由這些點(diǎn)組成的線并不一定完全包含在這個(gè)形狀之內(nèi)。
默認(rèn)情況下,地理空間索引是假設(shè)你的值都介于-180~180。可以根據(jù)需要在ensureIndex中設(shè)置更大或者更小的索引邊界值:
> db.star.trek.ensureIndex({"light-years" : "2d"}, {"min" : -1000, "max" : 1000})
這會(huì)創(chuàng)建一個(gè)2000×2000大小的空間索引。
使用"2d"索引進(jìn)行查詢比使用"2dsphere"要簡(jiǎn)單許多。可以直接使用"$near"或者"$within",而不必帶有"$geometry"子對(duì)象。可以直接指定坐標(biāo):
> db.hyrule.find({"tile" : {"$near" : [20, 21]}})
這樣會(huì)返回hyrule集合內(nèi)的全部文檔,按照距離(20,21)這個(gè)點(diǎn)的距離排序。如果沒(méi)有指定文檔數(shù)量限制,默認(rèn)最多返回100個(gè)文檔。如果不需要這么多結(jié)果,應(yīng)該根據(jù)需要設(shè)置返回文檔的數(shù)量以節(jié)省服務(wù)器資源。例如,下面的代碼只會(huì)返回距離(20,21)最近的10個(gè)文檔:
> db.hyrule.find({"tile" : {"$near" : [20, 21]}}).limit(10)
"$within"可以查詢出某個(gè)形狀(矩形、圓形或者是多邊形)范圍內(nèi)的所有文檔。如果要使用矩形,可以指定"$box"選項(xiàng):
> db.hyrule.find({"tile" : {"$within" : {"$box" : [[10, 20], [15, 30]]}}})
"$box"接受一個(gè)兩元素的數(shù)組:第一個(gè)元素指定左下角的坐標(biāo),第二個(gè)元素指定右上角的坐標(biāo)。
類似地,可以使用"$center"選項(xiàng)返回圓形范圍內(nèi)的所有文檔,這個(gè)選項(xiàng)也是接受一個(gè)兩元素?cái)?shù)組作為參數(shù):第一個(gè)元素是一個(gè)點(diǎn),用于指定圓心;第二個(gè)參數(shù)用于指定半徑:
> db.hyrule.find({"tile" : {"$within" : {"$center" : [[12, 25], 5]}}})
還可以使用多個(gè)點(diǎn)組成的數(shù)組來(lái)指定多邊形:
> db.hyrule.find( ... {"tile" : {"$within" : {"$polygon" : [[0, 20], [10, 0], [-10, 0]]}}})
這個(gè)例子會(huì)查詢出包含給定三角形內(nèi)的點(diǎn)的所有文檔。列表中的最后一個(gè)點(diǎn)會(huì)被連接到第一個(gè)點(diǎn),以便組成多邊形。
使用GridFS存儲(chǔ)文件GridFS是MongoDB的一種存儲(chǔ)機(jī)制,用來(lái)存儲(chǔ)大型二進(jìn)制文件。下面列出了使用GridFS作為文件存儲(chǔ)的理由。
使用GridFS能夠簡(jiǎn)化你的棧。如果已經(jīng)在使用MongoDB,那么可以使用GridFS來(lái)代替獨(dú)立的文件存儲(chǔ)工具。
GridFS會(huì)自動(dòng)平衡已有的復(fù)制或者為MongoDB設(shè)置的自動(dòng)分片,所以對(duì)文件存儲(chǔ)做故障轉(zhuǎn)移或者橫向擴(kuò)展會(huì)更容易。
當(dāng)用于存儲(chǔ)用戶上傳的文件時(shí),GridFS可以比較從容地解決其他一些文件系統(tǒng)可能會(huì)遇到的問(wèn)題。例如,在GridFS文件系統(tǒng)中,如果在同一個(gè)目錄下存儲(chǔ)大量的文件,沒(méi)有任何問(wèn)題。
在GridFS中,文件存儲(chǔ)的集中度會(huì)比較高,因?yàn)镸ongoDB是以2 GB為單位來(lái)分配數(shù)據(jù)文件的。
GridFS也有一些缺點(diǎn)。
GridFS的性能比較低:從MongoDB中訪問(wèn)文件,不如直接從文件系統(tǒng)中訪問(wèn)文件速度快。
如果要修改GridFS上的文檔,只能先將已有文檔刪除,然后再將整個(gè)文檔重新保存。MongoDB將文件作為多個(gè)文檔進(jìn)行存儲(chǔ),所以它無(wú)法在同一時(shí)間對(duì)文件中的所有塊加鎖。
通常來(lái)說(shuō),如果你有一些不常改變但是經(jīng)常需要連續(xù)訪問(wèn)的大文件,那么使用GridFS再合適不過(guò)了。
GridFS入門使用GridFS最簡(jiǎn)單的方式是使用mongofiles工具。所有的MongoDB發(fā)行版中都包含了mongofiles,可以用它在GridFS中上傳文件、下載文件、查看文件列表、搜索文件,以及刪除文件。
與其他的命令行工具一樣,運(yùn)行mongofiles --help就可以查看它的可用選項(xiàng)了。
在下面這個(gè)會(huì)話中,首先用mongofiles從文件系統(tǒng)中上傳一個(gè)文件到GridFS,然后列出GridFS中的所有文件,最后再將之前上傳過(guò)的文件從GridFS中下載下來(lái):
$ echo "Hello, world" > foo.txt $ ./mongofiles put foo.txt connected to: 127.0.0.1 added file: { _id: ObjectId("4c0d2a6c3052c25545139b88"), filename: "foo.txt", length: 13, chunkSize: 262144, uploadDate: new Date(1275931244818), md5: "a7966bf58e23583c9a5a4059383ff850" } done! $ ./mongofiles list connected to: 127.0.0.1 foo.txt 13 $ rm foo.txt $ ./mongofiles get foo.txt connected to: 127.0.0.1 done write to: foo.txt $ cat foo.txt Hello,world
在上面的例子中,使用mongofiles執(zhí)行了三種基本操作:put、list和get。put操作可以將文件系統(tǒng)中選定的文件上傳到GridFS;list操作可以列出GridFS中的文件;get操作與put相反,用于將GridFS中的文件下載到文件系統(tǒng)中。mongofiles還支持另外兩種操作:用于在GridFS中搜索文件的search操作和用于從GridFS中刪除文件的delete操作。
在MongoDB驅(qū)動(dòng)程序中使用GridFS所有客戶端驅(qū)動(dòng)程序都提供了GridFS API。例如,可以用PyMongo(MongoDB的Python驅(qū)動(dòng)程序)執(zhí)行與上面直接使用mongofiles一樣的操作:
>>> from pymongo import Connection >>> import gridfs >>> db = Connection().test >>> fs = gridfs.GridFS(db) >>> file_id = fs.put("Hello, world", filename="foo.txt") >>> fs.list() [u"foo.txt"] >>> fs.get(file_id).read() "Hello, world"
PyMongo中用于操作GridFS的API與mongofiles非常像:可以很方便地執(zhí)行put、get和list操作。幾乎所有MongoDB驅(qū)動(dòng)程序都遵循這種基本模式對(duì)GridFS進(jìn)行操作,當(dāng)然通常也會(huì)提供一些更高級(jí)的功能。關(guān)于特定驅(qū)動(dòng)程序?qū)ridFS的操作,可以查詢相關(guān)驅(qū)動(dòng)程序的文件。
揭開(kāi)GridFS的面紗GridFS是一種輕量級(jí)的文件存儲(chǔ)規(guī)范,用于存儲(chǔ)MongoDB中的普通文檔。MongoDB服務(wù)器幾乎不會(huì)對(duì)GridFS請(qǐng)求做“特殊”處理,所有處理都由客戶端的驅(qū)動(dòng)程序和工具負(fù)責(zé)。
GridFS背后的理念是:可以將大文件分割為多個(gè)比較大的塊,將每個(gè)塊作為獨(dú)立的文檔進(jìn)行存儲(chǔ)。由于MongoDB支持在文檔中存儲(chǔ)二進(jìn)制數(shù)據(jù),所以可以將塊存儲(chǔ)的開(kāi)銷降到非常低。除了將文件的每一個(gè)塊多帶帶存儲(chǔ)之外,還有一個(gè)文檔用于將這些塊組織在一起并存儲(chǔ)該文件的元信息。
GridFS中的塊會(huì)被存儲(chǔ)到專用的集合中。塊默認(rèn)使用的集合是fs.chunks,不過(guò)可以修改為其他集合。在塊集合內(nèi)部,各個(gè)文檔的結(jié)構(gòu)非常簡(jiǎn)單:
{ "_id" : ObjectId("..."), "n" : 0, "data" : BinData("..."), "files_id" : ObjectId("...") }
與其他的MongoDB文檔一樣,塊也都擁有一個(gè)唯一的"_id"。另外,還有如下幾個(gè)鍵。
"files_id"
塊所屬文件的元信息。
"n"
塊在文件中的相對(duì)位置。
"data"
塊所包含的二進(jìn)制數(shù)據(jù)。
每個(gè)文件的元信息被保存在一個(gè)多帶帶的集合中,默認(rèn)情況下這個(gè)集合是fs.files。這個(gè)文件集合中的每一個(gè)文檔表示GridFS中的一個(gè)文件,文檔中可以包含與這個(gè)文件相關(guān)的任意用戶自定義元信息。除用戶自定義的鍵之外,還有幾個(gè)鍵是GridFS規(guī)范規(guī)定必須要有的。
"_id"
文件的唯一id,這個(gè)值就是文件的每個(gè)塊文檔中"files_id"的值。
"length"
文件所包含的字節(jié)數(shù)。
"chunkSize"
組成文件的每個(gè)塊的大小,單位是字節(jié)。這個(gè)值默認(rèn)是256 KB,可以在需要時(shí)進(jìn)行調(diào)整。
"uploadDate"
文件被上傳到GridFS的日期。
"md5"
文件內(nèi)容的md5校驗(yàn)值,這個(gè)值由服務(wù)器端計(jì)算得到。
這些必須字段中最有意思(或者說(shuō)能夠見(jiàn)名知意)的一個(gè)可能是"md5"。"md5"字段的值是由MongoDB服務(wù)器使用filemd5命令得到的,這個(gè)命令可以用來(lái)計(jì)算上傳到GridFS的塊的md5校驗(yàn)值。這意味著,用戶可以通過(guò)檢查文件的md5校驗(yàn)值來(lái)確保文件上傳正確。
如上面所說(shuō),在fs.files中,除了這些必須字段外,可以使用任何自定義的字段來(lái)保存必需的文件元信息。可能你希望在文件元信息中保存文件的下載次數(shù)、MIME類型或者用戶評(píng)分。
只要理解了GridFS底層的規(guī)范,自己就可以很容易地實(shí)現(xiàn)一些驅(qū)動(dòng)程序沒(méi)有提供的輔助功能。例如,可以使用distinct命令得到GridFS中保存文件的文件名集合(集合中的每個(gè)文件名都是唯一的)。
> db.fs.files.distinct("filename") [ "foo.txt" , "bar.txt" , "baz.txt" ]
這樣,在加載或者收集文件相關(guān)信息時(shí),應(yīng)用程序可以擁有非常大的靈活性.
上一篇文章:MongoDB指南---14、特殊的索引和集合:固定集合、TTL索引、全文本索引
下一篇文章:MongoDB指南---16、聚合
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/19576.html
摘要:下面列出了使用作為文件存儲(chǔ)的理由。如果已經(jīng)在使用,那么可以使用來(lái)代替獨(dú)立的文件存儲(chǔ)工具。在中,文件存儲(chǔ)的集中度會(huì)比較高,因?yàn)槭且詾閱挝粊?lái)分配數(shù)據(jù)文件的。揭開(kāi)的面紗是一種輕量級(jí)的文件存儲(chǔ)規(guī)范,用于存儲(chǔ)中的普通文檔。 上一篇文章:MongoDB指南---14、特殊的索引和集合:固定集合、TTL索引、全文本索引下一篇文章:MongoDB指南---16、聚合 地理空間索引 MongoDB支持...
摘要:固定集合不能被分片。為固定集合指定文檔數(shù)量限制時(shí),必須同時(shí)指定固定集合的大小。沒(méi)有索引的集合默認(rèn)情況下,每個(gè)集合都有一個(gè)索引。 上一篇文章:MongoDB指南---13、索引類型、索引管理下一篇文章:MongoDB指南---15、特殊的索引和集合:地理空間索引、使用GridFS存儲(chǔ)文件 本章介紹MongoDB中一些特殊的集合和索引類型,包括: 用于類隊(duì)列數(shù)據(jù)的固定集合(capped...
摘要:固定集合不能被分片。為固定集合指定文檔數(shù)量限制時(shí),必須同時(shí)指定固定集合的大小。沒(méi)有索引的集合默認(rèn)情況下,每個(gè)集合都有一個(gè)索引。 上一篇文章:MongoDB指南---13、索引類型、索引管理下一篇文章:MongoDB指南---15、特殊的索引和集合:地理空間索引、使用GridFS存儲(chǔ)文件 本章介紹MongoDB中一些特殊的集合和索引類型,包括: 用于類隊(duì)列數(shù)據(jù)的固定集合(capped...
摘要:將返回結(jié)果限制為前個(gè)。所以,聚合的結(jié)果必須要限制在以內(nèi)支持的最大響應(yīng)消息大小。包含字段和排除字段的規(guī)則與常規(guī)查詢中的語(yǔ)法一致。改變字符大小寫的操作,只保證對(duì)羅馬字符有效。只對(duì)羅馬字符組成的字符串有效。 上一篇文章:MongoDB指南---15、特殊的索引和集合:地理空間索引、使用GridFS存儲(chǔ)文件下一篇文章:MongoDB指南---17、MapReduce 如果你有數(shù)據(jù)存儲(chǔ)在Mon...
摘要:將返回結(jié)果限制為前個(gè)。所以,聚合的結(jié)果必須要限制在以內(nèi)支持的最大響應(yīng)消息大小。包含字段和排除字段的規(guī)則與常規(guī)查詢中的語(yǔ)法一致。改變字符大小寫的操作,只保證對(duì)羅馬字符有效。只對(duì)羅馬字符組成的字符串有效。 上一篇文章:MongoDB指南---15、特殊的索引和集合:地理空間索引、使用GridFS存儲(chǔ)文件下一篇文章:MongoDB指南---17、MapReduce 如果你有數(shù)據(jù)存儲(chǔ)在Mon...
閱讀 608·2021-11-18 13:12
閱讀 1327·2021-11-15 11:39
閱讀 2488·2021-09-23 11:22
閱讀 6222·2021-09-22 15:15
閱讀 3669·2021-09-02 09:54
閱讀 2320·2019-08-30 11:10
閱讀 3254·2019-08-29 14:13
閱讀 2919·2019-08-29 12:49