和我一起学习 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 论坛,而不是在这里评论。在推特或邮件上给我发送你问题的链接,我会尽力提供帮助。