假如在 users 集合中插入以下文档:
> db.users.insert( ... { ... "address": { ... "city": "Hebei", ... "country": "China", ... "postcode": "000000" ... }, ... "tags": [ ... "music", ... "cricket", ... "blogs" ... ], ... "name": "cdsy" ... } ... ) WriteResult({ "nInserted" : 1 })
在上面的文档中包含了一个名为 address 的子文档和一个名为 tags 的数组。
假设要想根据集合内 tags 字段中的某个值来搜索用户文档,就需要我们为集合中的 tags 字段创建索引。想要在数组类型的字段上创建索引,需要为数组中的每个字段依次创建单独的索引。
在下面的示例中,当我们在 tags 字段上创建索引时,MongoDB 会自动在 music、cricket 和 blogs 等值上创建单独的索引。
> db.users.createIndex({"tags":1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 2, "numIndexesAfter" : 3, "ok" : 1 }
索引创建成功后,我们可以像下面这样来搜索集合中的文档:
> db.users.find({tags:"cricket"}).pretty() { "_id" : ObjectId("603f571d5e514debed504a39"), "address" : { "city" : "Hebei", "country" : "China", "postcode" : "000000" }, "tags" : [ "music", "cricket", "blogs" ], "name" : "cdsy" }
若要验证在搜索的过程中是否正确的使用了索引,可以使用前面介绍的 explain() 方法。
> db.users.find({tags:"cricket"}).explain() { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "cdsy.users", "indexFilterSet" : false, "parsedQuery" : { "tags" : { "$eq" : "cricket" } }, "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "tags" : 1 }, "indexName" : "tags_1", "isMultiKey" : true, "multiKeyPaths" : { "tags" : [ "tags" ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "tags" : [ "[\"cricket\", \"cricket\"]" ] } } }, "rejectedPlans" : [ ] }, "serverInfo" : { "host" : "LAPTOP-MDE57TIS", "port" : 27017, "version" : "4.0.10", "gitVersion" : "c389e7f69f637f7a1ac3cc9fae843b635f20b766" }, "ok" : 1 }
若运行结果中存在 "cursor":"BtreeCursor tags_1" 则说明查询中正确使用了索引。
假设我们要根据 address 子文档的 city、country、postcode 等字段来搜索文档,由于所有这些字段都是 address 子文档的一部分,所以我们需要为子文档上的所有字段创建索引。
要在子文档的所有三个字段上创建索引,可以使用如下所示的代码:
> db.users.ensureIndex({"address.city":1,"address.country":1,"address.postcode":1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 3, "numIndexesAfter" : 4, "ok" : 1 }
索引创建成功后,我们就可以使用 address 子文档中的任何字段来搜索集合中的数据了,如下所示:
> db.users.find({"address.city":"Hebei"}).pretty() { "_id" : ObjectId("603f571d5e514debed504a39"), "address" : { "city" : "Hebei", "country" : "China", "postcode" : "000000" }, "tags" : [ "music", "cricket", "blogs" ], "name" : "cdsy" }
另外,在查询时也可以设置多个查询条件,如下所示:
> db.users.find({"address.city":"Hebei", "address.country":"China"}).pretty() { "_id" : ObjectId("603f571d5e514debed504a39"), "address" : { "city" : "Hebei", "country" : "China", "postcode" : "000000" }, "tags" : [ "music", "cricket", "blogs" ], "name" : "cdsy" }