2015-02-09 76 views
0

在我使用MongoDB時,我開始理解MongoDB索引的問題。問題是MongoDB索引有時不會強制查詢兩端邊界。下面是在查詢的數據庫中,我遇到了一個輸出:MongoDB索引邊界約束

查詢:

db.user.find({transaction:{$elemMatch:{product:"mobile", firstTransaction:{$gte:ISODate("2015-01-01"), $lt:ISODate("2015-01-02")}}}}).hint("transaction.product_1_transaction.firstTransaction_1").explain() 

輸出:

"cursor" : "BtreeCursor transaction.firstTransaction_1_transaction.product_1", 
          "isMultiKey" : true, 
          "n" : 622, 
          "nscannedObjects" : 350931, 
          "nscanned" : 6188185, 
          "nscannedObjectsAllPlans" : 350931, 
          "nscannedAllPlans" : 6188185, 
          "scanAndOrder" : false, 
          "indexOnly" : false, 
          "nYields" : 235851, 
          "nChunkSkips" : 0, 
          "millis" : 407579, 
          "indexBounds" : { 
            "transaction.firstTransaction" : [ 
              [ 
                true, 
                ISODate("2015-01-02T00:00:00Z") 
              ] 
            ], 
            "transaction.product" : [ 
              [ 
                "mobile", 
                "mobile" 
              ] 
            ] 
          }, 

正如你可以看到在上面的例子爲firstTransaction場一個綁定的末端真實而不是我提到的日期。我發現解決方法是min(),max()函數。我試過這些,但他們似乎沒有使用嵌入式文檔(事務是一個包含firstTransaction,產品等字段的子文檔數組)。我收到以下錯誤:

查詢:

db.user.find({transaction:{$elemMatch:{product:'mobile'}}}).min({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-01")}}}).max({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-02")}}}) 

輸出:

planner returned error: unable to find relevant index for max/min query 

firstTransaction字段建立索引,雖然還有產品&其複合索引了。我不知道這裏出了什麼問題。

樣品文件:

{ 
_id: UUID (indexed by default), 
name: string, 
dob: ISODate, 
addr: string, 
createdAt: ISODate (indexed), 
. 
. 
., 
transaction:[ 
{ 
firstTransaction: ISODate(indexed), 
lastTransaction: ISODate(indexed), 
amount: float, 
product: string (indexed), 
. 
. 
. 
},... 
], 
other sub documents... 
} 
+0

這將是相當有益的看到你的查詢,而不僅僅是'explain'的輸出...... – mnemosyn 2015-02-09 09:52:13

回答

1

這是正確的行爲。你不能總是與$lte$gte的索引範圍相交 - 有時它會給出不正確的結果。例如,考慮文檔

{ "x" : [{ "a" : [4, 6] }] } 

本文檔匹配查詢

db.test.find({ "x" : { "$elemMatch" : { "a" : { "$gte" : 5, "$lte" : 5 } } } }); 

如果我們在{ "x.a" : 1 }定義一個指數,這兩個指數範圍是[5, infinity],和[-infinity, 5]。相交他們將給[5, 5]和使用此索引綁定將不匹配文檔 - 不正確!

你能提供一個示例文檔,並告訴我們更多關於你想要做什麼的查詢嗎?使用上下文,可能有另一種方法來編寫使用更緊密索引邊界的查詢。

+0

我明白了你的觀點。儘管我的field-firstTransaction不是整個集合中的數組,我想限制兩個索引的結束,以限制對文檔的搜索以獲得性能。我希望給出的示例文檔有所幫助。 – harshad 2015-02-10 08:50:01

+0

這個示例顯示索引邊界行爲涉及到一個數組 - 但重點是MongoDB不強制字段的類型,所以任何字段總是可以有一個數組值。因此,即使我們不允許在嵌入文檔中存在數組字段的情況下與索引邊界相交,我們仍然不允許與邊界相交。 – wdberkeley 2015-02-10 14:59:41

+0

另外,您是否可以描述查詢的目的,即它試圖爲應用程序實現的目標以及示例文檔?您將無法實現您可能認爲應以當前形式的查詢應用的「完美」索引邊界。 – wdberkeley 2015-02-10 15:01:07