和我一起学习 MongoDB






2.87/5 (6投票s)
在这里,我们将通过一些练习来学习 MongoDB,我们将讨论 Mongo Shell、如何配置 MongoDB、MongoDB 中的索引是什么等等。
引言
这将是一系列关于 MongoDB 的文章。在这里,我们将通过一些练习来学习 MongoDB,我们将讨论 Mongo Shell、如何配置 MongoDB、MongoDB 中的索引是什么等等。我们都知道什么是索引,你可能已经在任何关系型数据库中做到过,比如 SQL 和 MySQL。你对 MongoDB 做过索引吗?如果你的答案是“否”,不用担心,在这里我们将看到 MongoDB 中的索引,如果你的答案是“是”,请阅读这篇帖子,并在我可能出错的地方指正我。现在我们开始吧。
必备组件
我希望你已经对 MongoDB 有了基本了解,如果没有,我强烈建议你阅读 这些帖子。现在你有了基本概念,我假设你已经设置好了 MongoDB 开发环境。让我们回顾一下你可能已经做过的。
- 安装 MongoDB
- 设置 MongoDB 的环境变量
- 启动 MongoDB 服务
要为 MongoDB 设置环境变量,你可能需要在系统变量路径中添加一个新路径,值为“C:\Program Files\MongoDB\Server\3.4\bin”,请注意,版本号会根据你的 MongoDB 版本而变化。完成以上步骤后,你应该就能从命令行界面启动 Mongo 服务器和 Mongo Shell。
使用 CLI 设置 MongoDB
现在,我们打开命令行界面,为 Mongo 创建数据目录。我们需要为此创建一个目录。请按照以下命令进行操作
md \data
md \data\db
mongod
现在,让我们打开一个新的 CLI 并运行“mongo”命令,请不要担心你收到的警告,因为我们不是在处理生产数据,可能不需要进行安全加固和优化。

探索 MongoDB
连接到 MongoDB 后,默认情况下你会连接到 test DB。你可以通过运行命令 MongoDB Enterprise > db 来检查。
玩转 Mongo Shell
现在我们来使用一个新的数据库。
MongoDB Enterprise > use MongoIndex
switched to db MongoIndex
MongoDB Enterprise >
请注意,数据库 MongoIndex 目前不存在,因为我们还没有创建它。尽管如此,Mongo 还是将我们的上下文切换到了新数据库。你可以通过运行命令 show dbs 来查看。
一旦我们插入任何与该数据库相关的文档,该数据库就会被创建。现在我们要创建一个名为“User”的新集合,因此一旦我们向这个集合中插入一条记录,数据库也会自动创建。我们来做这件事。
MongoDB Enterprise > db.users.insert({"name":"Sibees Venu"})
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise >
现在如果你再次运行“show dbs”命令,MongoIndex 数据库就会显示出来。如果你想查看数据库中的集合,只需运行“show collections”命令即可。
MongoDB Enterprise > show collections
users
MongoDB Enterprise >
MongoDB 在处理数据方面非常友好,它不需要任何模式来启动。学习起来非常容易,对吧?
MongoDB 的另一个优点是它的 JavaScript 解释器 Shell,我们可以在其中键入 JavaScript 代码并运行。为了测试它,让我们创建一个变量并使用它。
MongoDB Enterprise > var name = "Sibeesh Venu"
MongoDB Enterprise > name
Sibeesh Venu
MongoDB Enterprise >
这样,我们就可以用 JavaScript 程序与数据库进行交互了。现在,让我们继续创建一个名为“Numbers”的集合,并在其中插入 26,000 行。我们该怎么做?是的,你说对了,我们要写一个 for 循环,mongo shell 提供了这种灵活性。让我们看看它的实际效果。
MongoDB Enterprise > for(i=0;i<=26000;i++){
... db.Numbers.insert({
... "number":i
... })
... }
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise >
这样我们就完成了。请注意,我们可以将命令分成多行,这使得在 Shell 中将复杂的代码分成更易读的格式。听起来不错?
尽管我们插入了 26,000 行,但它总是显示“"nInserted" : 1”,这是因为它计算的是操作次数,而不是单个文档。让我们通过检查计数来查看这一点。
MongoDB Enterprise > db.numbers.count()
0
MongoDB Enterprise > db.Numbers.count()
26001
MongoDB Enterprise >
请注意,它是区分大小写的。
MongoDB 中的索引
现在,如果你想查看任何特定的记录,你总是可以在 Shell 中这样写查询
MongoDB Enterprise > db.Numbers.find(
... {"number":24000}
... )
{ "_id" : ObjectId("5a8d3be2020a0071d115cf62"), "number" : 24000 }
MongoDB Enterprise >
因此,在查询中,我们使用“find”函数,并带有过滤器“number: 24000”,这样 Mongo 就可以返回 number 值等于 24000 的记录。现在我们得到了我们需要的输出,你想看看后台发生了什么吗?要做到这一点,我们可以使用“explain()”函数。
MongoDB Enterprise > db.Numbers.find( {"number":24000} ).explain()
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "MongoIndex.Numbers",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "number" : {
                                "$eq" : 24000
                        }
                },
                "winningPlan" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                                "number" : {
                                        "$eq" : 24000
                                }
                        },
                        "direction" : "forward"
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "PC292716",
                "port" : 27017,
                "version" : "3.4.9",
                "gitVersion" : "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
        },
        "ok" : 1
}
MongoDB Enterprise >
如果你需要有关执行的更多信息,可以将参数“executionStats”传递给“explain”函数。
参数总是区分大小写的,如果你输入错误,你会得到如下错误。所以请确保你传递的是
executionStats而不是executionstats。"MongoDB Enterprise > db.Numbers.find( {"number":24000} ).explain("executionstats")
2018-02-21T15:12:34.197+0530 E QUERY [thread1] Error: explain verbosity must be one of {'queryPlanner','executionStats','allPlansExecution'}
parseVerbosity@src/mongo/shell/explainable.js:22:1
constructor@src/mongo/shell/explain_query.js:83:27
DBQuery.prototype.explain@src/mongo/shell/query.js:520:24
@(shell):1:1"
MongoDB Enterprise > db.Numbers.find( {"number":24000} ).explain("executionStats")
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "MongoIndex.Numbers",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "number" : {
                                "$eq" : 24000
                        }
                },
                "winningPlan" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                                "number" : {
                                        "$eq" : 24000
                                }
                        },
                        "direction" : "forward"
                },
                "rejectedPlans" : [ ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1,
                "executionTimeMillis" : 13,
                "totalKeysExamined" : 0,
                "totalDocsExamined" : 26001,
                "executionStages" : {
                        "stage" : "COLLSCAN",
                        "filter" : {
                                "number" : {
                                        "$eq" : 24000
                                }
                        },
                        "nReturned" : 1,
                        "executionTimeMillisEstimate" : 11,
                        "works" : 26003,
                        "advanced" : 1,
                        "needTime" : 26001,
                        "needYield" : 0,
                        "saveState" : 203,
                        "restoreState" : 203,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "direction" : "forward",
                        "docsExamined" : 26001
                }
        },
        "serverInfo" : {
                "host" : "PC292716",
                "port" : 27017,
                "version" : "3.4.9",
                "gitVersion" : "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
        },
        "ok" : 1
}
MongoDB Enterprise >
现在你可以看到更多关于执行的信息,比如执行花了多少时间,检查了多少文档等等。如果你注意到,它检查了所有的 26001 条记录,耗时 13 毫秒。这只是一个例子,我们只有少量记录,如果我们有数百万条记录呢?检查所有记录将是一个糟糕的主意,对吧?那么我们该怎么办?有什么长远的解决方案吗?这就是 索引 的重要性发挥作用的地方。
让我们为我们要搜索的数字创建一个 Index。
MongoDB Enterprise > db.Numbers.createIndex({number:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
MongoDB Enterprise >
这里的 number 是一个特殊变量,不是 string。如你所见,我们已经创建了索引。你可以看到 createdCollectionAutomatically 的属性值为 false,因为集合已经创建,它不需要再次创建。
让我们再次运行查找查询。
MongoDB Enterprise > db.Numbers.find( {"number":24000} ).explain("executionStats")
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "MongoIndex.Numbers",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "number" : {
                                "$eq" : 24000
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "number" : 1
                                },
                                "indexName" : "number_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "number" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "number" : [
                                                "[24000.0, 24000.0]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [
                        {
                                "stage" : "FETCH",
                                "inputStage" : {
                                        "stage" : "IXSCAN",
                                        "keyPattern" : {
                                                "number" : 24000
                                        },
                                        "indexName" : "number_24000",
                                        "isMultiKey" : false,
                                        "multiKeyPaths" : {
                                                "number" : [ ]
                                        },
                                        "isUnique" : false,
                                        "isSparse" : false,
                                        "isPartial" : false,
                                        "indexVersion" : 2,
                                        "direction" : "forward",
                                        "indexBounds" : {
                                                "number" : [
                                                        "[24000.0, 24000.0]"
                                                ]
                                        }
                                }
                        }
                ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1,
                "executionTimeMillis" : 36,
                "totalKeysExamined" : 1,
                "totalDocsExamined" : 1,
                "executionStages" : {
                        "stage" : "FETCH",
                        "nReturned" : 1,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 3,
                        "advanced" : 1,
                        "needTime" : 0,
                        "needYield" : 0,
                        "saveState" : 1,
                        "restoreState" : 1,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "docsExamined" : 1,
                        "alreadyHasObj" : 0,
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 1,
                                "executionTimeMillisEstimate" : 0,
                                "works" : 2,
                                "advanced" : 1,
                                "needTime" : 0,
                                "needYield" : 0,
                                "saveState" : 1,
                                "restoreState" : 1,
                                "isEOF" : 1,
                                "invalidates" : 0,
                                "keyPattern" : {
                                        "number" : 1
                                },
                                "indexName" : "number_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "number" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "number" : [
                                                "[24000.0, 24000.0]"
                                        ]
                                },
                                "keysExamined" : 1,
                                "seeks" : 1,
                                "dupsTested" : 0,
                                "dupsDropped" : 0,
                                "seenInvalidated" : 0
                        }
                }
        },
        "serverInfo" : {
                "host" : "PC292716",
                "port" : 27017,
                "version" : "3.4.9",
                "gitVersion" : "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
        },
        "ok" : 1
}
MongoDB Enterprise >
由于我们已经为我们要搜索的内容创建了索引,因此在运行查询时,它只检查了该文档,这就是为什么 totalDocsExamined 的值为 1。索引对记录很少的数据库影响不大,但对包含数百万条记录的大型数据集影响巨大。使用这些简单的索引可以将执行时间缩短到几乎为零。
至此,我们完成了这篇帖子。我很快就会发布这个系列的续篇。
结论
非常感谢阅读。我是否遗漏了你认为需要的内容?你觉得这篇帖子有用吗?希望你喜欢这篇文章。请分享你宝贵的建议和反馈。
现在轮到你了。你有什么想法?
没有评论的博客就不算是博客,但请尽量保持话题相关。如果你有与本帖无关的问题,最好将其发布到 C# Corner、Code Project、Stack Overflow、ASP.NET 论坛,而不是在这里评论。在推特或邮件上给我发送你问题的链接,我会尽力提供帮助。

