因此,經過一堆測試後,事實證明查詢需要重寫,以便充分利用多個索引。重寫的版本是:
{
"$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/。