架构中具有不可预知字段集的工作负荷可以使用通配符索引来支持针对任意或未知字段的查询,以优化性能。
通配符索引在以下方案中非常有用:
- 查询对文档中任何字段进行筛选,使通过单个命令对所有字段编制索引比单独为每个字段编制索引更容易。
- 在文档中对大多数字段进行筛选时,查询只需通过单个字段即可对除几个字段之外的所有字段编制索引,而不是单独为大多数字段编制索引。
为所有字段编制索引
设置通配符索引以方便查询所有可能的文档字段,包括具有未知或动态名称的文档字段。
db.collection.createIndex( { "$**": 1 } )
重要
对于大型集合,我们建议使用本文档后面定义的备用方法。
包括或排除特定字段
通配符索引也可以限制为特定字段,同时排除某些字段作为索引的目标。 让我们查看以下 Json 的示例。
{
"firstName": "Steve",
"lastName": "Smith",
"companyName": "Microsoft",
"division": "Azure",
"timeInOrgInYears": 7
}
我们可以控制索引行为,此示例限制在firstName、lastName和timeInOrgInYears字段上创建索引。
db.collection.createIndex( { "$**": 1 },
{"wildcardProjection" : { "firstName": 0
, "lastName": 0
, "companyName": 1
, "division": 1
, "timeInOrgInYears": 0
}
}
)
在通配符投影文档中,值 0 或 1 用来指示字段是包含在索引中(1),还是从索引中排除(0)。
用于为所有字段编制索引的替代方法
此示例介绍一个简单的解决方法,以最大程度地减少创建单个索引所需的工作量,直到通配符索引在 Azure DocumentDB 中正式发布为止。
请考虑以下 json 文档:
{
"firstName": "Steve",
"lastName": "Smith",
"companyName": "Microsoft",
"division": "Azure",
"subDivision": "Data & AI",
"timeInOrgInYears": 7,
"roles": [
{
"teamName" : "Windows",
"teamSubName" "Operating Systems",
"timeInTeamInYears": 3
},
{
"teamName" : "Devices",
"teamSubName" "Surface",
"timeInTeamInYears": 2
},
{
"teamName" : "Devices",
"teamSubName" "Surface",
"timeInTeamInYears": 2
}
]
}
使用通配符索引时,以下索引在封面下创建。
- db.collection.createIndex({"firstName": 1})
- db.collection.createIndex({“lastName”, 1})
- db.collection.createIndex({“companyName”, 1})
- db.collection.createIndex({“division”, 1})
- db.collection.createIndex({“subDivision”, 1})
- db.collection.createIndex({“timeInOrgInYears”, 1})
- db.collection.createIndex({“subDivision”, 1})
- db.collection.createIndex({“roles.teamName”, 1})
- db.collection.createIndex({“roles.teamSubName”, 1})
- db.collection.createIndex({“roles.timeInTeamInYears”, 1})
虽然此示例文档只需要显式索引 10 个字段的组合,但具有数百或数千个字段的大型文档在单独编制字段索引时容易出现繁琐和错误。
本文档其余部分详述的 jar 文件使较大文档中的索引字段更简单。 jar 采用示例 JSON 文档作为输入,分析文档并为每个字段执行 createIndex 命令,而无需用户干预。
先决条件
Java 21
部署虚拟机后,使用 SSH 连接到计算机,并使用以下命令安装 CQLSH:
# Install default-jdk
sudo apt update
sudo apt install openjdk-21-jdk
用于为所有字段创建单个索引的示例 jar
克隆包含 Java 示例的存储库,以遍历 JSON 文档结构中的每个字段,并为文档中的每个字段执行 createIndex 操作。
git clone https://github.com/Azure-Samples/cosmosdb-mongodb-vcore-wildcard-indexing.git
如果没有对解决方案进行更改,则无需生成克隆的存储库。 名为azure-cosmosdb-mongo-data-indexer-1.0-SNAPSHOT.jar的生成可运行 jar 已包含在 runnableJar/ 文件夹中。 要执行 jar,可以通过指定以下必需参数:
- 预配群集时使用的用户名和密码的 Azure DocumentDB 群集连接字符串
- Azure DocumentDB 数据库
- 要编制索引的集合
- 包含集合的文档结构的 json 文件的位置。 本文档由 jar 文件解析,以提取每个字段并执行单独的 createIndex 操作。
java -jar azure-cosmosdb-mongo-data-indexer-1.0-SNAPSHOT.jar mongodb+srv://<user>:<password>@abinav-test-benchmarking.global.mongocluster.cosmos.azure.cn/?tls=true&authMechanism=SCRAM-SHA-256&retrywrites=false&maxIdleTimeMS=120000 cosmicworks employee sampleEmployee.json
跟踪 createIndex 操作的状态
jar 文件的设计是为了不等待每个 createIndex 操作的响应。 索引是在服务器上异步创建的,可以跟踪群集上的索引生成作的进度。
请考虑以下示例来跟踪“cosmicworks”数据库的索引进度。
use cosmicworks;
db.currentOp()
当 createIndex 操作正在进行中时,响应如下所示。
{
"inprog": [
{
"shard": "defaultShard",
"active": true,
"type": "op",
"opid": "30000451493:1719209762286363",
"op_prefix": 30000451493,
"currentOpTime": "2024-06-24T06:16:02.000Z",
"secs_running": 0,
"command": { "aggregate": "" },
"op": "command",
"waitingForLock": false
},
{
"shard": "defaultShard",
"active": true,
"type": "op",
"opid": "30000451876:1719209638351743",
"op_prefix": 30000451876,
"currentOpTime": "2024-06-24T06:13:58.000Z",
"secs_running": 124,
"command": { "createIndexes": "" },
"op": "workerCommand",
"waitingForLock": false,
"progress": {},
"msg": ""
}
],
"ok": 1
}