因此,经过一堆测试后,事实证明查询需要重写,以便充分利用多个索引。重写的版本是:
{
"$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/。