2016-04-20 84 views
0

我想了解索引如何應用到這個MongoDB的查詢:

{ 
    "account_id" : 1234, 
    "supplier_id" : { 
     "$gt" : 0 
    }, 
    "$or" : [ 
     { 
      "po_number" : { 
       "$regex" : "blahblah", 
       "$options" : "i" 
      } 
     }, 
     { 
      "shipping.first_name" : { 
       "$regex" : "blahblah", 
       "$options" : "i" 
      } 
     }, 
     { 
      "shipping.last_name" : { 
       "$regex" : "blahblah", 
       "$options" : "i" 
      } 
     }, 
     { 
      "shipping.company" : { 
       "$regex" : "blahblah", 
       "$options" : "i" 
      } 
     }, 
     { 
      "consumer_order_number" : "blahblah" 
     }, 
     { 
      "invoices.invoice_number" : "blahblah" 
     }, 
     { 
      "shipments.tracking_number" : "blahblah" 
     } 
    ], 
    "test_flag" : { 
     "$in" : [0,null] 
    } 
} 

我明白,這可能是一個緩慢的查詢,但我想看看別人會攻擊創建索引。這可能是重新組織查詢的問題嗎?

回答

0

因此,經過一堆測試後,事實證明查詢需要重寫,以便充分利用多個索引。重寫的版本是:

{ 
"$or" : [ 
    { 
     "po_number" : {"$regex" : "blahblah", "$options" : "i"} 
     "account_id" : 1234, 
     "supplier_id" : {"$gt" : 0}, 
     "test_flag" : {"$in" : [0,null]} 
    }, 
    { 
     "shipping.first_name" : {"$regex" : "blahblah", "$options" : "i"} 
     "account_id" : 1234, 
     "supplier_id" : {"$gt" : 0}, 
     "test_flag" : {"$in" : [0,null]} 
    }, 
    { 
     "shipping.last_name" : {"$regex" : "blahblah", "$options" : "i"} 
     "account_id" : 1234, 
     "supplier_id" : {"$gt" : 0}, 
     "test_flag" : {"$in" : [0,null]} 
    }, 
    { 
     "shipping.company" : {"$regex" : "blahblah", "$options" : "i"} 
     "account_id" : 1234, 
     "supplier_id" : {"$gt" : 0}, 
     "test_flag" : {"$in" : [0,null]} 
    }, 
    { 
     "consumer_order_number" : "blahblah" 
     "account_id" : 1234, 
     "supplier_id" : {"$gt" : 0}, 
     "test_flag" : {"$in" : [0,null]} 
    }, 
    { 
     "invoices.invoice_number" : "blahblah" 
     "account_id" : 1234, 
     "supplier_id" : {"$gt" : 0}, 
     "test_flag" : {"$in" : [0,null]} 
    }, 
    { 
     "shipments.tracking_number" : "blahblah" 
     "account_id" : 1234, 
     "supplier_id" : {"$gt" : 0}, 
     "test_flag" : {"$in" : [0,null]} 
    } 
], 

}

注意的唯一頂級元素是如何「$或」。如果還有其他頂級元素,則只能使用單個索引。我創建了以下索引,查詢最終使用:

db.Order.ensureIndex({po_number: 1, account_id: -1, supplier_id: -1}); 
db.Order.ensureIndex({"shipping.first_name": 1, account_id: -1, supplier_id: -1}); 
db.Order.ensureIndex({"shipping.last_name": 1, account_id: -1, supplier_id: -1}); 
db.Order.ensureIndex({"shipping.company": 1, account_id: -1, supplier_id: -1}); 
db.Order.ensureIndex({consumer_order_number: 1, account_id: -1, supplier_id: -1}); 
db.Order.ensureIndex({"invoices.invoice_number": 1, account_id: -1, supplier_id: -1}); 
db.Order.ensureIndex({"shipments.tracking_number": 1, account_id: -1, supplier_id: -1}); 

作爲一個側面說明,我也發現了很多的速度通過改變$正則表達式條目。

由於不區分大小寫,此版本是最慢的版本,並且允許在字符串的中間找到該術語。

{"$regex" : "blahblah", "$options" : "i"} 

如果不區分大小寫可以不完成,我們可以假定的任期可以永遠是一個「打頭......」值,再下面是非常快:

{"$regex" : "^blahblah"} 

請注意,最後沒有「*」,因爲它是隱含的。見https://docs.mongodb.org/v3.0/reference/operator/query/regex/

0

我將與您的查詢的三個主要領域是創建一個複合索引開始,因爲它是一個低掛水果的方式:

db.yourcollection.createIndex({account_id: 1, test_flag: 1, supplier_id: 1}) 

的1S表明增加鍵順序創建索引範圍。特別是,它支持supplier_id上的$ gt查詢。

訂單可以使用,特別是最後兩個訂單,但account_id可能應該保持在第一位:您的查詢具有高度選擇性,所以最好有一個索引將相同的account_id保持在一起。

然後$或部分查詢將在內存中執行,如果上述三個字段是有選擇性的,這應該足夠好。