2012-09-22 34 views
2

有沒有辦法在MongoDB中只有部分字段上創建索引,例如前10個字符?我找不到記錄(或在此處詢問)。僅在MongoDB中的字段的一部分進行索引

MySQL相當於CREATE INDEX part_of_name ON customer (name(10));

原因:我有一個字段的集合,其長度從幾個字符到最多1000個字符,平均50個字符。由於有一億份左右的文件,很難滿足內存中的全部索引(根據統計數據,對索引已經有400%的數據進行8%的測試)。僅索引該字段的第一部分將使索引大小減少約75%。在大多數情況下,搜索詞很短,不是全文搜索。

解決方法是爲每個項目添加第二個10(小寫)字符的字段,索引,然後添加邏輯以在搜索項超過10個字符時過濾結果(並且該額外字段爲is probably needed anyway不區分大小寫的搜索,除非有更好的方法)。看起來像一個醜陋的方式來做到這一點。

[後來補充]

我嘗試添加第二字段中,從主字段包含前12個字符,小寫。這並不是一個很大的成功。

以前,平均對象大小爲50字節,但我忘記了包含_id和其他開銷,所以我的主字段長度(只有一個)平均接近30個字節而不是50.然後,第二個字段索引包含_id和其他開銷。

最終結果(對於我的8%樣本),主字段的索引是415MB,在12字節的字段是330MB - 只有20%的空間節省,不值得。我可以複製整個字段(解決不區分大小寫的搜索問題),但實際上它看起來應該重新考慮MongoDB是否適合作業(或者只是購買更多內存並使用兩倍的磁盤空間)。

[加入甚至更晚]

這是一個典型的文檔,與源字段和短小寫字段:

{ "_id" : ObjectId("505d0e89f56588f20f000041"), "q" : "Continental Airlines", "f" : "continental " } 

索引:

db.test.ensureIndex({q:1}); 

db.test.ensureIndex({f:1}); 

在「F」索引,在較短的領域工作,是「q」索引大小的80%。我並不是想暗示我在索引中包含了_id,只是需要在某處使用該索引來顯示索引的位置點t o,所以這是一個開銷,可能有助於解釋爲什麼一個較短的密鑰造成如此小的差異。

訪問索引將基本上是隨機的,它的任何部分都比任何其他訪問更可能被訪問。整個文件的總索引大小可能爲5GB,因此對於那個索引來說不是極端的。爲其他搜索案例及其相關索引和小寫數據副本添加一些其他字段,開始加起來,並且更有可能進行分頁和交換(這是一個8GB服務器),這是我爲什麼開始研究更多簡明的指數。

+0

FWIW,你可以看看像Solr這樣的文本搜索;我使用它與MongoDB一起進行文檔搜索,並且它運行得非常漂亮。我讓Solr擅長擅長什麼,讓Mongo擅長擅長什麼。 –

+0

是的克里斯,這就是我的意見,我的意見是關於重新考慮Mongo是否是正確的工具 - Mongo(裝載和索引非常快!)沒有錯,只是這不是它的理想選擇(特別是一旦我添加更復雜的搜索)。 Elasticsearch是最重要的。 –

+0

除非您打算使用外部文本引擎,否則8GB可能無法滿足此用例的需求。你是對的:全文搜索目前不是MongoDB的強項之一。 –

回答

2

MongoDB無法爲字段值的一部分創建索引。正如你所建議的,你最好的辦法是創建第二個領域。

因爲無論如何您都需要第二個字段進行高效的不區分大小寫搜索,所以沒有理由不創建它。

的索引不存儲文檔的「_id」字段,它們存儲DiscLoc結構,這是一個非常低級別的結構:在這裏看到的細節

另外,請注意,「醜陋」實際上是「關係思維」的人工製品。 (作爲一個長時間的SQL用戶,我經常發現關於學習MongoDB最困難的部分是un - 學習我的關係思維。)在面向文檔的數據庫中,反規範化和複製數據實際上是最佳實踐。

+0

我已經嘗試添加第二個字段,其中包含主字段的前12個字符,小寫。在這裏無法適應結果(沒有意識到有一個限制),所以我會編輯這個問題。 –

+0

除非您使用它來搜索,否則第二個字段索引不應包含_id。你確切的ensure_index()命令是什麼?示例文檔中包含什麼內容?你正在運行什麼查詢? –

+0

另外:請注意,你不需要在內存中有完整的索引:只是工作集。您的應用程序將在整個集合中進行隨機訪問,還是會存在數據局部性? –

相關問題