我试图了解如何将索引应用于此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 :(得分:0)
我开始的方式是在查询的主要三个字段上创建一个复合索引,因为它是一个悬而未决的结果:
db.yourcollection.createIndex({account_id: 1, test_flag: 1, supplier_id: 1})
1表示按增加键顺序创建的范围索引。特别是,它支持supplier_id上的$ gt查询。
订单可以使用,特别是最后两个,但是account_id可能应该保持优先:您的查询对它有高度选择性,因此最好有一个索引将相同的account_id保持在一起。
然后将在内存中执行$或部分查询,如果以上三个字段是选择性的,那么这应该足够好。
答案 1 :(得分: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条目找到了很多速度。
由于不区分大小写,此版本最慢,并且允许在字符串的中间找到该术语。
{"$regex" : "blahblah", "$options" : "i"}
如果不能不区分大小写,我们可以假设该术语始终是"以...开始..."价值,那么以下是非常快的:
{"$regex" : "^blahblah"}
请注意,没有" *"最后,因为它暗示。请参阅https://docs.mongodb.org/v3.0/reference/operator/query/regex/。