2015-02-09 3 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 один конец связанный является true вместо даты, о которой я упоминал. Я обнаружил, что обходной путь для этого - функции 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

ответ

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

У меня есть ваша точка. Хотя мое поле-firstTransaction не является массивом всей коллекции, и я хочу ограничить два конца индекса, чтобы ограничить поиск документов, чтобы повысить производительность. Я надеюсь, что данный образец документа поможет. – harshad

+0

Пример, показывающий, что поведение границ индекса связано с массивом, но дело в том, что MongoDB не применяет типы для полей, поэтому любое поле всегда может иметь значение массива. Поэтому, даже если нам не разрешено пересекать границы индекса только тогда, когда есть поля массива во встроенном документе, мы по-прежнему не разрешаем пересекать границы вообще. – wdberkeley

+0

Также вы могли бы описать цель запроса, то есть то, чего оно пытается достичь для вашего приложения, вместе с образцом документа? Вы не сможете достичь «идеальных» границ индекса, которые, по вашему мнению, должны применяться с запросом в его текущей форме. – wdberkeley

Смежные вопросы