部分索引
部分索引对满足指定筛选条件的集合中的文档编制索引。Amazon DocumentDB 5.0 基于实例的集群支持部分索引功能。
创建部分索引
要创建部分索引,请使用带 partialFilterExpression
选项的 createIndex()
方法。例如,以下操作在订单集合中创建唯一的复合索引,该索引为具有 OrderID
且字段 isDelivered
为“true”的文档编制索引:
db.orders.createIndex( {"category": 1, "CustomerId": 1, "OrderId": 1}, {"unique": true, "partialFilterExpression": {"$and": [ {"OrderId": {"$exists": true}}, {"isDelivered": {"$eq": false}} ]} } )
支持的运算符
$eq
$exists
$and(仅限顶层)
$gt/$gte/$lt/$lte(只有查询中断言的筛选器与部分筛选表达式完全匹配时才使用索引扫描)(参见“限制”)
使用部分索引进行查询
使用部分索引可以实现以下查询模式:
-
查询谓词与部分索引筛选表达式完全匹配:
db.orders.find({"$and": [ {"OrderId": {"$exists": true}}, {"isDelivered": {"$eq": false}} ]}).explain()
-
查询筛选器的预期结果是部分筛选器的逻辑子集:
db.orders.find({"$and": [ {"OrderId": {"$exists": true}}, {"isDelivered": {"$eq": false}}, {"OrderAmount": {"$eq": "5"}} ]}).explain()
-
查询子谓词可以与其他索引结合使用:
db.orders.createIndex({"anotherIndex":1}) db.orders.find({ "$or": [ {"$and": [ {"OrderId": {"$exists": true}}, {"isDelivered": {"$eq": false}} ]}, {"anotherIndex": {"$eq": 5}} ] }).explain()
注意
如果有效的话,查询计划程序可以选择使用集合扫描而不是索引扫描。这通常出现在非常小的集合或会返回集合大部分内容的查询中。
部分索引功能
列出部分索引
使用 getIndex
操作,列出带有 partialFilterExpression 的部分索引。例如,发出的 getIndex
操作列出了带有键、名称和 partialFilterExpressions 字段的部分索引:
db.orders.getIndexes()
此示例返回以下输出:
[
{
"v" : 4,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "ecommerceApp.orders"
},
{
"v" : 4,
"unique" : true,
"key" : {
"category" : 1,
"" : 1,
"CustomerId" : 1,
"OrderId" : 1
},
"name" : "category_1_CustID_1_OrderId_1",
"ns" : "ecommerceApp.orders",
"partialFilterExpression" : {
"$and" : [
{"OrderId": {"$exists": true}},
{"isDelivered": {"$eq": false}}
]
}
}
]
相同 key:order 上的多个部分筛选表达式
可以为相同的字段组合 (key:order) 创建不同的部分索引。这些索引必须使用不同的名称。
db.orders.createIndex( {"OrderId":1}, { name:"firstPartialIndex", partialFilterExpression:{"OrderId":{"$exists": true}} } )
db.orders.createIndex( {"OrderId":1}, { name:"secondPartialIndex", partialFilterExpression:{"OrderId":{"$gt": 1000}} } )
运行 getIndexes
操作列出集合中的所有索引:
db.orders.getIndexes()
这些示例返回以下输出:
[
{
"v" : 4,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "ecommerceApp.orders"
},
{
"v" : 4,
"key" : {
"OrderId" : 1
},
"name" : "firstPartialIndex",
"ns" : "ecommerceApp.orders",
"partialFilterExpression" : {"OrderId":{"$exists": true}}
},
{
"v" : 4,
"key" : {
"OrderId" : 1
},
"name" : "secondPartialIndex",
"ns" : "ecommerceApp.orders",
"partialFilterExpression" : {"OrderId":{"$gt": 1000}}
}
]
重要
索引名称必须不同,并且只能按名称删除。
具有部分和 TTL 属性的索引
您还可以通过在索引创建过程中同时指定 partialFilterExpression
和 expireAfterSeconds
选项来创建具有部分和 TTL 属性的索引。这使就可以更好地控制当前要从集合中删除的文档。
例如,您可能有一个可识别要在特定时间段后删除的文档的 TTL 索引。您现在可以使用部分索引选项,为何时删除文档提供额外的条件:
db.orders.createIndex( { "OrderTimestamp": 1 }, { expireAfterSeconds: 3600 , partialFilterExpression: { "isDelivered": { $eq: true } } } )
此示例返回以下输出:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1,
"operationTime" : Timestamp(1234567890, 1)
}
运行 getIndexes
操作以列出集合中存在的索引:
db.orders.getIndexes() [ { "v" : 4, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.orders" }
此示例返回以下输出:
[
{
"v": 4,
"key": {
"_id": 1
},
"name": "_id_",
"ns": "ecommerceApp.orders"
},
{
"v": 4,
"key": {
"OrderTimestamp": 1
},
"name": "OrderTimestamp_1",
"ns": "ecommerceApp.orders",
"partialFilterExpression": {
"isDelivered": {
"$eq": true
}
},
"expireAfterSeconds": 3600
}
]
部分索引限制
以下限制适用于部分索引功能:
-
Amazon DocumentDB 中的不等于查询只有在查询筛选器谓词与
partialFilterExpression
完全匹配且具有相同的数据类型时才会使用部分索引。注意
对于上述情况,甚至是
$hint
也不能用于强制执行 IXSCAN。在以下示例中,
partialFilterExpression
仅适用于field1
,但不适用field2
:db.orders.createIndex( {"OrderAmount": 1}, {"partialFilterExpression": { OrderAmount : {"$gt" : 5}}} ) db.orders.find({OrderAmount : {"$gt" : 5}}) // Will use partial index db.orders.find({OrderAmount : {"$gt" : 6}}) // Will not use partial index db.orders.find({OrderAmount : {"$gt" : Decimal128(5.00)}}) // Will not use partial index
-
不支持带数组运算符的
partialFilterExpression
。以下操作会产生错误:db.orders.createIndex( {"CustomerId":1}, {'partialFilterExpression': {'OrderId': {'$eq': [1000, 1001, 1002]}}} )
partialFilterExpression 字段不支持以下运算符:
$all
(数组运算符)$mod
(数组运算符)$or
$xor
$not
$nor
筛选表达式和筛选器应具有相同的数据类型。