<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ MongoDB - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ freeCodeCamp 是一个免费学习编程的开发者社区，涵盖 Python、HTML、CSS、React、Vue、BootStrap、JSON 教程等，还有活跃的技术论坛和丰富的社区活动，在你学习编程和找工作时为你提供建议和帮助。 ]]>
        </description>
        <link>https://www.freecodecamp.org/chinese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ MongoDB - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/chinese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 11 May 2026 09:58:42 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/chinese/news/tag/mongo/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ MongoDB 基础教程 ]]>
                </title>
                <description>
                    <![CDATA[ MongoDB 是一个丰富的面向文档的 NoSQL 数据库。 在本文中，我会分享一些有关 MongoDB 命令的基本知识，例如查询、过滤数据、删除、更新等等。 好的，我们开始吧！ 配置 为了使用 MongoDB，首先需要在计算机上安装 MongoDB。为此，请访问官方下载中心 [https://www.mongodb.com/download-center/community]，下载适用于你的操作系统的版本。在这篇文章里，我会以 Windows 为例。 下载 MongoDB 社区服务器设置后，你将依次点击“下一个”完成安装。完成后，转到安装了 MongoDB 的 C 驱动器。打开程序文件，然后选择 MongoDB 目录。 C: -> Program Files -> MongoDB -> Server -> 4.0(version) -> bin 在 bin 目录中，你会发现几个有趣的可执行文件。  * mongod  * mongo 我们看一下这两个文件。 mongod 代表“ Mongo Daemon”。mongod ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/learn-mongodb/</link>
                <guid isPermaLink="false">5ff7d58b39641a0517d5359e</guid>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 数据库 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Wed, 02 Jun 2021 09:00:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2021/01/pietro-jeng-n6B49lTx7NM-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>MongoDB 是一个丰富的面向文档的 NoSQL 数据库。</p><p>在本文中，我会分享一些有关 MongoDB 命令的基本知识，例如查询、过滤数据、删除、更新等等。</p><p><strong>好的，我们开始吧！</strong></p><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/news/content/images/2021/01/image.png" class="kg-image" alt="image" width="600" height="400" loading="lazy"></figure><h3 id="-"><strong>配置</strong></h3><p>为了使用 MongoDB，首先需要在计算机上安装 MongoDB。为此，请访问<a href="https://www.mongodb.com/download-center/community">官方下载中心</a>，下载适用于你的操作系统的版本。在这篇文章里，我会以 Windows 为例。</p><p>下载 MongoDB 社区服务器设置后，你将依次点击“下一个”完成安装。完成后，转到安装了 MongoDB 的 C 驱动器。打开程序文件，然后选择 MongoDB 目录。</p><pre><code>C: -&gt; Program Files -&gt; MongoDB -&gt; Server -&gt; 4.0(version) -&gt; bin</code></pre><p>在 bin 目录中，你会发现几个有趣的可执行文件。</p><ul><li>mongod</li><li>mongo</li></ul><p>我们看一下这两个文件。</p><p>mongod 代表“ Mongo Daemon”。mongod 是 MongoDB 使用的后台进程。mongod 的主要目的是管理所有 MongoDB 服务器任务，例如：接受请求，响应客户端和内存管理。</p><p>mongo 是可以与客户端（例如，系统管理员和开发人员）进行交互的命令行外壳。</p><p>现在，让我们看看如何启动和运行该服务器。在 Windows 上，首先需要在 C 驱动器中创建几个目录。在 C 驱动器中打开命令提示符，然后执行以下操作：</p><pre><code>C:\&gt; mkdir data/dbC:\&gt; cd dataC:\&gt; mkdir db</code></pre><p>这些目录的目的是 MongoDB 需要一个文件夹来存储所有数据。MongoDB 的默认数据目录路径是驱动器上的 <code>/data/db</code>。因此，有必要像这样提供这些目录。</p><p>如果启动不带这些目录的 MongoDB 服务器，则可能会看到以下错误：</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/r04FRmRGqKUaclGh4ZDo3YsMwOlXMVm2T3bJ" class="kg-image" alt="r04FRmRGqKUaclGh4ZDo3YsMwOlXMVm2T3bJ" width="600" height="400" loading="lazy"><figcaption>尝试启动 mongodb 服务器，不含 \data\db 目录</figcaption></figure><p>创建完这两个文件后，再次转到 mongodb 目录中的 bin 文件夹，然后打开其中的 shell。运行以下命令：</p><pre><code>mongod</code></pre><p>瞧！ 现在，我们的 MongoDB 服务器已启动并正在运行！？</p><p>为了使用此服务器，我们需要一个中介器。在 bind 文件夹中打开另一个命令窗口，然后运行以下命令：</p><pre><code>mongo</code></pre><p>运行此命令后，导航到运行 mongod 命令的外壳程序（这是我们的服务器）。你会在最后看到“接受连接”消息。这意味着我们的安装和配置成功！</p><p>只需在 mongo shell 中运行即可：</p><pre><code>db</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/TK2JGg4JXAj0eG9JBzl89ABEF3JuKAwnw2dx" class="kg-image" alt="TK2JGg4JXAj0eG9JBzl89ABEF3JuKAwnw2dx" width="600" height="400" loading="lazy"><figcaption>最初你有一个 db 叫作 ‘test’</figcaption></figure><h4 id="--1"><strong>配置环境变量</strong></h4><p>为了节省时间，你可以设置环境变量。在 Windows 中，通过以下菜单完成：</p><pre><code>Advanced System Settings -&gt; Environment Variables -&gt; Path(Under System Variables) -&gt; Edit</code></pre><p>只需复制我们的 bin 文件夹的路径，然后运行它。在我的这个示例里，是这样的：</p><p> <code>C:\Program Files\MongoDB\Server\4.0\bin</code></p><p>现在你就完成设置了！</p><h3 id="-mongodb"><strong>使用 MongoDB</strong></h3><p>大量的 GUI 图形用户界面（例如 MongoDB Compass，Studio 3T 等）可和 MongoDB &nbsp;服务器一起使用。</p><p>它们提供了图形界面，因此你可以轻松地使用数据库并执行查询，而无需使用 Shell 并手动键入查询。</p><p>但是在本文中，我们将使用命令提示符来完成工作。</p><p>现在我们深入研究 MongoDB 命令，这些命令将帮助你在将来的项目中使用。</p><ul><li>打开命令提示符，然后键入 <code>mongod</code> 以启动 MongoDB 服务器。</li><li>打开另一个外壳，然后键入 <code>mongo</code> 以连接到 MongoDB 数据库服务器。</li></ul><h4 id="1-"><strong>1. 确定你目前在哪个数据库</strong></h4><pre><code>db</code></pre><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/o6puQoPSpGCW8-AgizHzAv3Qpywtzsgwd26N" class="kg-image" alt="o6puQoPSpGCW8-AgizHzAv3Qpywtzsgwd26N" width="600" height="400" loading="lazy"></figure><p>此命令将显示你当前所在的数据库。<code>test</code> 是默认情况下的初始数据库。</p><h4 id="2-"><strong>2. 罗列数据库</strong></h4><pre><code>show databases</code></pre><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/Q-G8NzP5OAXh0Y3OfdOtqFxlFG-tLErPlPSi" class="kg-image" alt="Q-G8NzP5OAXh0Y3OfdOtqFxlFG-tLErPlPSi" width="600" height="400" loading="lazy"></figure><p>我目前有四个数据库：<code>CrudDB</code>， <code>admin</code>， <code>config</code> 和 <code>local</code>。</p><h4 id="3-"><strong><strong><strong>3. 访问某个数据库</strong></strong></strong></h4><pre><code>use &lt;your_db_name&gt;</code></pre><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/UIRueBuX-r6nRXA-qd6Uv95IBd0UbhVvMZtZ" class="kg-image" alt="UIRueBuX-r6nRXA-qd6Uv95IBd0UbhVvMZtZ" width="600" height="400" loading="lazy"></figure><p>在这里，我已移至 <code>local</code> 数据库。你可以使用命令 <code>db</code> 打印出当前数据库的名称，进行检查。</p><h4 id="4-"><strong><strong><strong>4. 创建一个数据库</strong></strong></strong></h4><p>使用 RDBMS（关系数据库管理系统），我们可以获得数据库、表、行和列。</p><p>但是，在 NoSQL 数据库（例如 MongoDB）中，数据以 BSON 格式（JSON 的二进制版本）存储。它们存储在称为“集合”的结构中。</p><p>在 SQL 数据库中，这些类似于表。</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/e7ygVKXaPcqcqCyvurAeUzAbmmREoA6p72V2" class="kg-image" alt="e7ygVKXaPcqcqCyvurAeUzAbmmREoA6p72V2" width="600" height="400" loading="lazy"></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/oxeGaPqbZ2pmmZx3WcDo8CXIL4J09PbecBWW" class="kg-image" alt="oxeGaPqbZ2pmmZx3WcDo8CXIL4J09PbecBWW" width="600" height="400" loading="lazy"><figcaption>SQL terms and NoSQL terms by <a href="https://www.blogger.com/profile/18437865869379626284" rel="noopener" target="_blank" title="author profile" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 17.6px; vertical-align: baseline; background-color: transparent; color: var(--gray90); text-decoration: underline; cursor: pointer; word-break: break-word;">Victoria Malaya</a></figcaption></figure><p>接下来，我们谈谈如何在 mongo shell 中创建数据库。</p><pre><code>use &lt;your_db_name&gt;</code></pre><p>等一下，我们之前有这个命令！ 为什么我再次使用它？</p><p>在 MongoDB 服务器中，如果你的数据库已经存在，则使用该命令将导航到你的数据库。</p><p>但是，如果数据库尚不存在，则 MongoDB 服务器将为你创建数据库。然后，它将导航到其中。</p><p>创建新数据库后，运行 <code>show database</code> 命令将不会显示你新创建的数据库。这是因为，当数据库包含一些数据（文档）后，它才会显示在你的数据库列表中。</p><h4 id="5-"><strong><strong><strong>5. 创建一个集合</strong></strong></strong></h4><p>使用 <code>use</code> 命令导航到新创建的数据库。</p><p>实际上，有两种创建集合的方法。</p><p>一种方法是将数据插入到集合中：</p><pre><code>db.myCollection.insert({"name": "john", "age" : 22, "location": "colombo"})</code></pre><p>即使该集合不存在，这也将创建你的集合 <code>myCollection</code>。然后它将插入带有 <code>name</code> 和 <code>age</code> 的文档。这些是无上限的集合。</p><p>第二种方法如下所示：</p><p>2.1 创建一个无上限的集合</p><pre><code>db.createCollection("myCollection")</code></pre><p>2.2 创建一个有上限的集合</p><pre><code>db.createCollection("mySecondCollection", {capped : true, size : 2, max : 2})</code></pre><p>这样，你将无需插入数据即可创建集合。</p><p>“有上限的集合”规定了最大的文档数，可防止文档溢出。在此示例中，我通过将其值设置为 <code>true</code> 启用上限。</p><p><code>size : 2</code> 表示限制为 2MB，<code>max: 2</code> 将最大文档数设置为 2。</p><p>现在，如果你尝试在 <code>mySecondCollection</code> 中插入两个以上的文档，并使用 <code>find</code> &nbsp;命令（我们将在稍后讨论），你只会看到最近插入的文档。请记住，这并不意味着第一个文档已被删除——它只是未显示。</p><h4 id="6-"><strong><strong><strong>6. 插入数据</strong></strong></strong></h4><p>我们可以将数据插入到新集合或之前创建的集合中。</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/uO4agHbI85kMJrQmF1L9pMmhn0WcgngmoPsI" class="kg-image" alt="uO4agHbI85kMJrQmF1L9pMmhn0WcgngmoPsI" width="600" height="400" loading="lazy"><figcaption>数据存储在 JSON 中</figcaption></figure><p>有三种插入数据的方法：</p><ul><li><code>insertOne()</code> 仅用于插入单个文档</li><li><code>insertMany()</code> 用于插入多个文档</li><li><code>insert()</code> 用于插入所需数量的文档</li></ul><p>下面是一些示例：</p><ul><li><strong><strong>insertOne()</strong></strong></li></ul><pre><code>db.myCollection.insertOne(
  {
    "name": "navindu", 
    "age": 22
  }
)</code></pre><ul><li><strong><strong>insertMany()</strong></strong></li></ul><pre><code>db.myCollection.insertMany([
  {
    "name": "navindu", 
    "age": 22
  },
  {
    "name": "kavindu", 
    "age": 20
  },

  {
    "name": "john doe", 
    "age": 25,
    "location": "colombo"
  }
])</code></pre><p><code>insert()</code> 方法类似于 <code>insertMany()</code> 方法。</p><p>另外，请注意，我们在文档中为 <code>John Doe</code> 插入了一个名为 <code>location</code> 的新属性。因此，如果你使用 <code>find</code>，则只会看到 <code>john doe</code> 具有 <code>location</code> 属性。</p><p>对于 NoSQL 数据库（例如 MongoDB），这可能是一个优势，有利于可扩展性。</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/QyCgwWUHWoporNunUvoRgdVry-x0QyA8qSxd" class="kg-image" alt="QyCgwWUHWoporNunUvoRgdVry-x0QyA8qSxd" width="600" height="400" loading="lazy"><figcaption>成功插入数据</figcaption></figure><h4 id="7-"><strong><strong><strong>7. 查询数据</strong></strong></strong></h4><p>你可以通过以下方法查询集合中的所有数据：</p><pre><code>db.myCollection.find()</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/rzcViLqDrTy5gqSFoY6n3N7dciNxFTY62eRL" class="kg-image" alt="rzcViLqDrTy5gqSFoY6n3N7dciNxFTY62eRL" width="600" height="400" loading="lazy"><figcaption>结果</figcaption></figure><p>如果你想通过更清晰的方式查看此数据，只需在其末尾添加 <code>.pretty()</code> 即可。这将以漂亮的 JSON 格式显示文档。</p><pre><code>db.myCollection.find().pretty()</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/gMIbpNqjr9jmJ3YVDZruX1skX0PCvSruuZWB" class="kg-image" alt="gMIbpNqjr9jmJ3YVDZruX1skX0PCvSruuZWB" width="600" height="400" loading="lazy"><figcaption>结果</figcaption></figure><p>等等，在这些示例中，你是否注意到了类似 <code>_id</code> 的东西？</p><p>无论何时插入文档，MongoDB 都会自动添加一个 <code>_id</code> 字段。该字段唯一地标识每个文档。如果你不想显示它，只需运行以下命令：</p><pre><code>db.myCollection.find({}, _id: 0).pretty()</code></pre><p>接下来，我们看一下过滤数据。</p><p>如果要显示某些特定文档，则可以指定要显示的文档的单个详细信息。</p><pre><code>db.myCollection.find(
  {
    name: "john"
  }
)</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/TiBBNNp9gmxtPXaHd5BSZ7MkSrv1JkRzkMI1" class="kg-image" alt="TiBBNNp9gmxtPXaHd5BSZ7MkSrv1JkRzkMI1" width="600" height="400" loading="lazy"><figcaption>结果</figcaption></figure><p>假设你只想显示年龄在 25 岁以下的人。您可以使用 <code>$lt</code> 对此进行过滤。</p><pre><code>db.myCollection.find(
  {
    age : {$lt : 25}
  }
)</code></pre><p>同样，<code>$gt</code> 表示大于，<code>$lte</code> 表示“小于或等于”，<code>$gte</code> 表示“大于或等于”，<code>$ne</code> 是“不等于”。</p><h4 id="8-"><strong><strong><strong>8. 更新文档</strong></strong></strong></h4><p>假设你想更新某人的地址或年龄，该怎么做？ 请看下一个例子：</p><pre><code>db.myCollection.update({age : 20}, {$set: {age: 23}})</code></pre><p>第一个参数是要更新哪个文档的字段。在这里，我为简单起见指定了 <code>age</code>。在生产环境中，你可以使用 <code>_id</code> 字段。</p><p>最好使用 <code>_id</code> 之类的内容来更新特定的一行。 这是因为多个字段可以具有相同的年龄和名称。 因此，如果更新一行，它将影响具有相同名称和年龄的所有行。</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/qQH53vM6-peOzS-z9k5YjMoS9R2z1APJrXvB" class="kg-image" alt="qQH53vM6-peOzS-z9k5YjMoS9R2z1APJrXvB" width="600" height="400" loading="lazy"><figcaption>结果</figcaption></figure><p>如果你使用新属性（例如 <code>location</code>）更新文档，则文档将使用新属性进行更新。如果你执行 <code>find</code>，那么结果是：</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/YqJpPAw7d5NPSTzStCevUmgoDTm6FkgPLZ-7" class="kg-image" alt="YqJpPAw7d5NPSTzStCevUmgoDTm6FkgPLZ-7" width="600" height="400" loading="lazy"><figcaption>结果</figcaption></figure><p>如果你需要从单个文档中删除某个属性，则可以执行以下操作（假设你希望删除 <code>age</code>）：</p><pre><code>db.myCollection.update({name: "navindu"}, {$unset: age});</code></pre><h4 id="9-"><strong><strong><strong>9. 删除一个文档</strong></strong></strong></h4><p>如前所述，当你更新或删除文档时，你只需要指定 <code>_id</code> 即可，而不是 <code>name</code>，<code>age</code>，<code>location</code>。</p><pre><code>db.myCollection.remove({name: "navindu"});</code></pre><h4 id="10-"><strong><strong><strong>10. 删除一个集合</strong></strong></strong></h4><pre><code>db.myCollection.remove({});</code></pre><p>注意，这不等于 <code>drop()</code> 方法。不同之处在于 <code>drop()</code> 用于删除集合中的所有文档，而 <code>remove()</code> 方法用于删除集合本身以及所有文档。</p><h3 id="--2"><strong>逻辑运算符</strong></h3><p>MongoDB 提供逻辑运算符。下图总结了不同类型的逻辑运算符。</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/xO27jGeclafiAUt0a0VYRifhDpISvZcIkhRD" class="kg-image" alt="xO27jGeclafiAUt0a0VYRifhDpISvZcIkhRD" width="600" height="400" loading="lazy"></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/VsHbrchxUETWqCFhZc6QvmSPUdrbfOHYEH3L" class="kg-image" alt="VsHbrchxUETWqCFhZc6QvmSPUdrbfOHYEH3L" width="600" height="400" loading="lazy"><figcaption>参考：MongoDB 手册</figcaption></figure><p>假设你要显示年龄小于 25 岁且位置在科伦坡的人，怎么做呢？</p><p>我们可以使用 <code>$and</code> 运算符！</p><pre><code>db.myCollection.find({$and:[{age : {$lt : 25}}, {location: "colombo"}]});</code></pre><p>最后，我们来谈谈聚合。</p><h3 id="--3"><strong>聚合</strong></h3><p>快速看一下我们了解到的有关 SQL 数据库中聚合函数的知识：</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/JHcuA7YLBiFiCBn1QiOS8NYCUELbGg-LKDSN" class="kg-image" alt="JHcuA7YLBiFiCBn1QiOS8NYCUELbGg-LKDSN" width="600" height="400" loading="lazy"><figcaption>SQL 数据库中的聚合函数，参考：Tutorial Gateway</figcaption></figure><p>简而言之，聚合对多个文档中的值进行分组并以某种方式进行汇总。</p><p>想象一下，如果我们在 <code>recordBook</code> 集合中有男女学生，而我们希望每个学生都有总数。为了获得男生和女生的总和，我们可以使用 <code>$group</code> 聚合函数。</p><pre><code>db.recordBook.aggregate([
  {
    $group : {_id : "$gender", result: {$sum: 1}}
  }  
]);</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/NeK7Wx3lQ1AaUhGD1VERqmaluAl9qrsXpDMs" class="kg-image" alt="NeK7Wx3lQ1AaUhGD1VERqmaluAl9qrsXpDMs" width="600" height="400" loading="lazy"><figcaption>结果</figcaption></figure><h4 id="--4"><strong>总结</strong></h4><p>我们讨论了 MongoDB 基础，将来构建应用程序时可能需要用到。希望你喜欢这篇文章。谢谢阅读！</p><p>如果你对此教程有任何疑问，请随时在下面的评论部分中进行评论，或者在 <a href="https://www.facebook.com/navinduuu">Facebook </a>或 <a href="https://twitter.com/NavinduJay">Twitter</a> 或 <a href="https://www.instagram.com/iamnavindu/">Instagram</a> 上与我联系。</p><p>下篇再见！ ❤️✌</p><p>原文：<a href="https://www.freecodecamp.org/news/learn-mongodb-a4ce205e7739/">How to get started with MongoDB in 10 minutes</a>，作者：Navindu Jayatilake</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ MongoDB Atlas 入门教程 ]]>
                </title>
                <description>
                    <![CDATA[ 对于以下挑战，你将使用 MongoDB 来存储数据。为了简化配置，你将使用名为 MongoDB Atlas 的服务。 创建一个  MongoDB Atlas 账号 MongoDB Atlas 是一个 MongoDB 数据库即服务平台，可以为你配置和托管数据库。然后，你唯一需要做的就是将数据上传到数据库。  * 在这里 [https://account.mongodb.com/account/register]注册一个新的 MongoDB Atlas 账号。  * 在注册表格中填写你的信息，然后点击 Sign up（注册）。 创建一个新的集群  * 在下一页填写你的组织名称、项目名称，选择 JavaScript 作为你的首选编程语言，然后点击绿色的 Continue（继续）按钮。  * 点击共享集群下的 Create a cluster（创建集群）按钮。这应该是唯一的免费选项。  * 在 Cloud Provider & Region（云提供商和区域）下拉列表中，将其保留为默认值（通常为 AWS）。  ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/get-started-with-mongodb-atlas/</link>
                <guid isPermaLink="false">603e13f7c354c605689eaaff</guid>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp.org ]]>
                </dc:creator>
                <pubDate>Wed, 03 Mar 2021 05:00:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2021/03/photo-1544383835-bda2bc66a55d-1.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>对于以下挑战，你将使用 MongoDB 来存储数据。为了简化配置，你将使用名为 MongoDB Atlas 的服务。</p><h2 id="-mongodb-atlas-"><strong><strong>创建一个</strong> <strong>MongoDB Atlas 账号</strong></strong></h2><p>MongoDB Atlas 是一个 MongoDB 数据库即服务平台，可以为你配置和托管数据库。然后，你唯一需要做的就是将数据上传到数据库。</p><ul><li>在<a href="https://account.mongodb.com/account/register">这里</a>注册一个新的 MongoDB Atlas 账号。</li><li>在注册表格中填写你的信息，然后点击 <strong><strong>Sign up</strong></strong>（注册）。</li></ul><h2 id="-">创建一个新的集群</h2><ul><li>在下一页填写你的组织名称、项目名称，选择 JavaScript 作为你的首选编程语言，然后点击绿色的 <strong><strong>Continue</strong></strong>（继续）按钮。</li><li>点击共享集群下的 <strong><strong>Create a cluster</strong></strong>（创建集群）按钮。这应该是唯一的免费选项。</li><li>在 <strong><strong>Cloud Provider &amp; Region</strong></strong>（云提供商和区域）下拉列表中，将其保留为默认值（通常为 AWS）。</li><li>在 <strong><strong>Cluster Tier</strong></strong>（集群计划）下拉列表中，将其保留为默认值：<code>M0 Sandbox (Shared RAM, 512 MB Storage)</code>。</li><li>在 <strong><strong>Cluster Name</strong></strong>（集群名称）下拉列表中，你可以为集群命名，也可以将其保留为默认名称 <code>Cluster 0</code>。</li><li>点击屏幕底部的绿色 <strong><strong>Create Cluster</strong></strong>（创建集群）按钮。</li><li>现在，你应该看到消息 <code>Your cluster is being created. New clusters take between 1-3 minutes to provision.</code>（正在创建集群，新集群需要 1-3 分钟的时间进行配置）。等待集群创建完成，然后再进行下一步。</li></ul><h2 id="--1">为数据库创建一个新用户</h2><ul><li>在屏幕的左侧，点击 <strong><strong>Database Access</strong></strong>（数据库访问）。</li><li>点击绿色的 <strong><strong>Add New Database User</strong></strong>（添加新的数据库用户）按钮。</li><li>输入新的用户名和密码。</li><li>在 <strong><strong>Database User Privileges</strong></strong>（数据库用户权限）下，将此保留为默认选项，即 <strong><strong>Read and write to any database</strong></strong>（读写任何数据库）。</li><li>点击 <strong><strong>Add User</strong></strong>（添加用户）按钮以创建你的新用户。</li></ul><h2 id="-ip-">允许所有 IP 地址访问</h2><ul><li>在屏幕的左侧，点击 <strong><strong>Network Access</strong></strong>（网络访问）。</li><li>点击绿色的 <strong><strong>Add IP Address</strong></strong>（添加 IP 地址）按钮。</li><li>点击 <strong><strong>ALLOW ACCESS FROM ANYWHERE</strong></strong>（允许从任何地方访问）按钮。你应该在 Access List Entry（访问列表）输入字段中看到 <code>0.0.0.0/0</code>。</li><li>点击绿色的 <strong><strong>Confirm</strong></strong>（确认）按钮。</li></ul><h2 id="--2">连接到你的集群</h2><ul><li>点击屏幕左下方绿色的 <strong><strong>Get Started</strong></strong>（开始）按钮，现在应该显示最后一步，即 <strong><strong>Connect to your cluster</strong></strong>（连接到你的集群），点击它。</li><li>在屏幕的左侧，点击 <strong><strong>Clusters</strong></strong>（集群）。</li><li>单击集群的 <strong><strong>Connect</strong></strong>（连接）按钮。</li><li>在弹出框中，单击 <strong><strong>Connect your application</strong></strong>（连接你的应用程序）。</li><li>你应该会看到类似于以下内容的 URI，用于连接你的数据库：<code>mongodb+srv://&lt;username&gt;:&lt;password&gt;@&lt;cluster-name&gt;.mongodb.net/&lt;db-name&gt;?retryWrites=true&amp;w=majority</code>。</li><li>单击 <strong><strong>Copy</strong></strong>（复制）按钮，将 URI 复制到剪贴板。</li></ul><p>请注意，你复制的 URI 的 <code>&lt;username&gt;</code>、<code>&lt;cluster-name&gt;</code>、和 <code>&lt;db-name&gt;</code>字段已经为你填写好。你需要做的就是将 <code>&lt;password&gt;</code> 字段替换为你在上一步中创建的字段。</p><p>就是这样——你现在有了 URI，可以将其添加到你的应用程序，并连接到数据库。请妥善保存这个 URI，以便以后使用。</p><p>原文：<a href="https://www.freecodecamp.org/news/get-started-with-mongodb-atlas/">MongoDB Atlas Tutorial – How to Get Started</a></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 通过 Node.js、MongoDB、Fastify 和 Swagger 构建高性能的 REST API 应用 ]]>
                </title>
                <description>
                    <![CDATA[ 作为 web 开发者，对构建高可用 REST API 应该并不陌生。 高可用 API 有如下衡量标准：  * 速度（API 响应时间）  * 文档（清晰简洁的文档，能够很好的描述 API）  * 架构和持续性（代码可维护可扩展） 这篇教程我们将要通过 Node.js、MongoDB、Fastify 和 Swagger 搭建高可用后端架构。 源代码已经托管到了 GitHub 3 [https://github.com/siegfriedgrimbeek/fastify-api] 上。 开始之前 你应该具有初级\中极 JavaScript 知识，了解 Node.js 和 MongoDB，知道什么是 REST APIS。 下面是相关链接：  * JavaScript 2 [https://developer.mozilla.org/bm/docs/Web/JavaScript]  * Node.js 1  ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/how-to-build-blazing-fast-rest-apis-with-node-js-mongodb-fastify-and-swagger/</link>
                <guid isPermaLink="false">5d22dc7bfbfdee429dc5ec28</guid>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ ZhichengChen ]]>
                </dc:creator>
                <pubDate>Wed, 03 Mar 2021 02:00:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2019/07/1-3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>作为 web 开发者，对构建高可用 REST API 应该并不陌生。</p><p>高可用 API 有如下衡量标准：</p><ul><li>速度（API 响应时间）</li><li>文档（清晰简洁的文档，能够很好的描述 API）</li><li>架构和持续性（代码可维护可扩展）</li></ul><p>这篇教程我们将要通过 Node.js、MongoDB、Fastify 和 Swagger 搭建高可用后端架构。</p><p>源代码已经托管到了 <a href="https://github.com/siegfriedgrimbeek/fastify-api" rel="nofollow noopener">GitHub 3</a> 上。</p><figure class="kg-card kg-image-card"><img src="http://img.youtube.com/vi/VxY_cz0VQXE/0.jpg" class="kg-image" alt="0" width="600" height="400" loading="lazy"></figure><h2 id="-">开始之前</h2><p>你应该具有初级\中极 JavaScript 知识，了解 Node.js 和 MongoDB，知道什么是 REST APIS。</p><p>下面是相关链接：</p><ul><li><a href="https://developer.mozilla.org/bm/docs/Web/JavaScript" rel="nofollow noopener">JavaScript 2</a></li><li><a href="https://codeburst.io/the-only-nodejs-introduction-youll-ever-need-d969a47ef219" rel="nofollow noopener">Node.js 1</a></li><li><a href="https://docs.mongodb.com/manual/introduction/" rel="nofollow noopener">MongoDB 1</a></li><li><a href="https://restful.io/an-introduction-to-api-s-cee90581ca1b" rel="nofollow noopener">REST APIS 3</a></li></ul><h3 id="--1">涉及的技术</h3><ul><li><a href="https://www.fastify.io/" rel="nofollow noopener">Fastify 3</a></li><li><a href="https://mongoosejs.com/" rel="nofollow noopener">Mongoose</a></li><li><a href="https://swagger.io/" rel="nofollow noopener">Swagger 1</a></li></ul><p>可以在标签页中打开这些链接，随时查阅。</p><h3 id="--2">需要安装的环境：</h3><ul><li><a href="https://nodejs.org/en/" rel="nofollow noopener">NodeJS/NPM</a></li><li><a href="https://docs.mongodb.com/manual/installation/" rel="nofollow noopener">MongoDB</a></li><li><a href="https://www.getpostman.com/" rel="nofollow noopener">Postman</a></li></ul><p>除此之外，还需要 <a href="https://ourcodeworld.com/articles/read/200/top-7-best-free-web-development-ide-for-javascript-html-and-css" rel="nofollow noopener">IDE</a> 和 终端，我在 Mac 用的是 <a href="https://www.iterm2.com/" rel="nofollow noopener">iTerm2</a> ，在 Windows 上用的是 <a href="https://hyper.is/" rel="nofollow noopener">Hyper</a>。</p><h2 id="--3">让我们开始吧</h2><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/optimized/1X/aa6ed96ac8cca8995c4d15ff3f8377b3dec98024_2_690x421.png" class="kg-image" alt="1_Jw9V__6jYhm2amP74D_0lw" width="600" height="400" loading="lazy"></figure><p>打开终端初始化项目，执行下面的代码：</p><pre><code class="language-bash">mkdir fastify-api
cd fastify-api
mkdir src
cd src
touch index.js
npm init
</code></pre><p>上面的代码，创建了两个新目录，然后切换到了新建的路径下，创建了一个 <code>index.js</code> 文件并通过 <a href="https://www.npmjs.com/" rel="nofollow noopener">npm</a> 初始化项目。</p><p>在初始化新项目的时候会提示输入一些值，这些值可以留空在稍后更新。</p><p>完成后，<code>src</code> 目录下生成了 <a href="https://alligator.io/nodejs/package-json/" rel="nofollow noopener">package.json</a>。在这个文件里你可以更改工程初始化时留空的值。</p><p>接下来安装将要用到的所有的依赖库：</p><pre><code>npm i nodemon mongoose fastify fastify-swagger boom
</code></pre><p>下面是在它们的官网引用的介绍：</p><h3 id="nodemon"><a href="https://github.com/remy/nodemon" rel="nofollow noopener">nodemon</a></h3><p>nodemon 是 node.js 应用的开发工具，当检测到目录下的文件改变时它会自动重启 node 应用。</p><p>使用 nodemon 不需要更改代码，它是 <code>node</code> 命令的封装，直接在执行脚本的时候用 <code>nodemon</code>替换 <code>node</code> 即可。</p><p>把下面的代码添加到 <code>package.json</code> 文件里来使用 nodemon：</p><pre><code class="language-json">"start": "./node_modules/nodemon/bin/nodemon.js ./src/index.js"
</code></pre><p>这时 <code>package.json</code> 文件应该这样：</p><pre><code class="language-json">{
  "name": "fastify-api",
  "version": "1.0.0",
  "description": "A blazing fast REST APIs with Node.js, MongoDB, Fastify and Swagger.",
  "main": "index.js",
  "scripts": {
  "start": "./node_modules/nodemon/bin/nodemon.js ./src/index.js",
  "test": "echo \"Error: no test specified\" &amp;&amp; exit 1"
},
  "author": "Siegfried Grimbeek &lt;siegfried.grimbeek@gmail.com&gt; (www.siegfriedgrimbeek.co.za)",
  "license": "ISC",
  "dependencies": {
  "boom": "^7.2.2",
  "fastify": "^1.13.0",
  "fastify-swagger": "^0.15.3",
  "mongoose": "^5.3.14",
  "nodemon": "^1.18.7"
  }
}
</code></pre><h3 id="mongoose"><a href="https://mongoosejs.com/" rel="nofollow noopener">mongoose</a></h3><p>Mongoose 提供了一个直截了当、基于 schema 的应用数据 model 解决方案。它包括了内置类型转换、校验、构建查询、业务逻辑钩子等功能，可直接使用。</p><h3 id="fastify-3"><a href="https://www.fastify.io/" rel="nofollow noopener">fastify 3</a></h3><p>Fastify 是一个高度专注于以最少的开销和强大的插件架构提供最佳开发者体验的 web 框架。Fastify 受到Hapi 和 Express 的启发，是目前最快的 web 框架之一。</p><h3 id="fastify-swagger-1"><a href="https://github.com/fastify/fastify-swagger" rel="nofollow noopener">fastify-swagger 1</a></h3><p><a href="https://swagger.io/" rel="nofollow noopener">Swagger 1</a> 文档生成器速度很快。它通过 routes 里声明的 schema 生成符合 swagger 规范的文档。</p><h3 id="boom"><a href="https://github.com/hapijs/boom" rel="nofollow noopener">boom</a></h3><p>boom 提供一个返回 HTTP 错误的工具集。</p><h2 id="--4">启动服务开始创建第一个路由</h2><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/optimized/1X/1533a0dfd2222a09f334de96f18e57535a6bfbe4_2_690x211.png" class="kg-image" alt="1_rocnESJrNWsRGXMygLfDCQ" width="600" height="400" loading="lazy"></figure><p>在 <code>index.js</code> 里添加如下代码：</p><pre><code class="language-javascript">// Require the framework and instantiate it
const fastify = require('fastify')({
  logger: true
})

// Declare a route
fastify.get('/', async (request, reply) =&gt; {
  return { hello: 'world' }
})

// Run the server!
const start = async () =&gt; {
  try {
    await fastify.listen(3000)
    fastify.log.info(`server listening on ${fastify.server.address().port}`)
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()
</code></pre><p>在这里引入了 Fastify 框架，声明了第一个 route 并在 <code>port 3000</code> 上启动了服务，代码很容易理解但是要注意初始化 Fastify 时传入了可选的对象：</p><pre><code class="language-javascript">// Require the fastify framework and instantiate it
const fastify = require('fastify')({
  logger: true
})
</code></pre><p>上面的代码开启了默认关闭的 Fastify 内置日志功能。</p><p>在终端的 <code>src</code> 目录下运行下面的代码：</p><pre><code>npm start
</code></pre><p>浏览器访问 <a href="http://localhost:3000/" rel="nofollow noopener">http://localhost:3000/</a> 会看到 <code>{hello:world}</code>。</p><p>回到 <code>index.js</code> 开始配置数据库。</p><h2 id="-mongodb-model">启动 MongoDB 创建 model</h2><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/optimized/1X/9b7ce6e492e1515078b340108a231189f9cfb3c7_2_690x186.png" class="kg-image" alt="1_Ce0gUe0LbnhL7ebnDGTp5w" width="600" height="400" loading="lazy"></figure><p>安装 MongoDB，打开终端运行以下命令启动 MongoDB。</p><pre><code>mongod
</code></pre><p>在 MongoDB 里不需要手动创建数据库。只需要在配置的时候指定数据库名，当数据存储的时候， MongoDB 会自动创建数据库。</p><p>在 <code>index.js</code> 里添加如下代码：</p><pre><code class="language-javascript">...
// Require external modules
const mongoose = require('mongoose')
// Connect to DB
mongoose.connect(‘mongodb://localhost/mycargarage’)
 .then(() =&gt; console.log(‘MongoDB connected…’))
 .catch(err =&gt; console.log(err))
...
</code></pre><p>在上面的代码里我们引入了 Mongoose 来连接 MongoDB 数据库。数据库名是 <code>mycargarage</code>，如果一切顺利，在终端里会看到 <code>MongoDB connected...</code>。</p><p>注意不需要手动重启 app，因为我们之前添加了 <code>Nodemon</code> 库。</p><p>现在数据库已经运行，可以创建第一个 Model 了。在 <code>src</code> 路径下创建一个名为 <code>models</code> 的新文件夹，在里面创建一个 <code>Car.js</code> 文件，添加如下代码：</p><pre><code class="language-javascript">// External Dependancies
const mongoose = require('mongoose')

const carSchema = new mongoose.Schema({
  title: String,
  brand: String,
  price: String,
  age: Number,
  services: {
    type: Map,
    of: String
  }
})

module.exports = mongoose.model('Car', carSchema)
</code></pre><p>上面的代码声明的 <code>carSchema</code> 包含了和 cars 相关的所有信息。除了两个基本数据类型: <code>String</code>和 <code>Number</code>。还用到了相对比较陌生的 <code>Map</code>，可以在<a href="https://thecodebarbarian.com/whats-new-in-mongoose-5.1-map-support.html" rel="nofollow noopener">这里 2</a>阅读更多。接着导出了 <code>carSchema</code>，以便在 app 里使用。</p><p>也可以把 routes、controllers 和 config 的代码都放到 <code>index.js</code> 文件里，但是为了代码可维护，这里每个组件都有它自己的文件夹。</p><h2 id="-car-controller">创建 car controller</h2><p>在 <code>src</code> 下创建 <code>controllers</code> 文件夹，在文件夹里创建 <code>carController.js</code> 文件：</p><pre><code class="language-javascript">// External Dependancies
const boom = require('boom')

// Get Data Models
const Car = require('../models/Car')

// Get all cars
exports.getCars = async (req, reply) =&gt; {
  try {
    const cars = await Car.find()
    return cars
  } catch (err) {
    throw boom.boomify(err)
  }
}

// Get single car by ID
exports.getSingleCar = async (req, reply) =&gt; {
  try {
    const id = req.params.id
    const car = await Car.findById(id)
    return car
  } catch (err) {
    throw boom.boomify(err)
  }
}

// Add a new car
exports.addCar = async (req, reply) =&gt; {
  try {
    const car = new Car(req.body)
    return car.save()
  } catch (err) {
    throw boom.boomify(err)
  }
}

// Update an existing car
exports.updateCar = async (req, reply) =&gt; {
  try {
    const id = req.params.id
    const car = req.body
    const { ...updateData } = car
    const update = await Car.findByIdAndUpdate(id, updateData, { new: true })
    return update
  } catch (err) {
    throw boom.boomify(err)
  }
}

// Delete a car
exports.deleteCar = async (req, reply) =&gt; {
  try {
    const id = req.params.id
    const car = await Car.findByIdAndRemove(id)
    return car
  } catch (err) {
    throw boom.boomify(err)
  }
}
</code></pre><p>carController.js</p><p>代码看起来有点长，其实很简单。</p><ul><li>引入了 boom 来处理错误：<code>boom.boomify(err)</code>。</li><li>导出了所有的函数以便在 route 里引入。</li><li>每个函数都是异步的，使用了 await 表达式，这样在执行异步函数的时会候暂停运行直到程序调用传入的 Promise 的 resolve，然后继续异步函数的执行并返回 resolved 值。<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function" rel="nofollow noopener">点击点解更多</a></li><li>每个函数代码都在 try/catch 语句里。<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch" rel="nofollow noopener">点击了解更多</a></li><li>每个函数都有两个参数：<code>req</code> (request) 和 <code>reply</code>。教程里只用到了 request 参数，用来访问 request body、 参数以及处理数据。<a href="https://www.fastify.io/docs/latest/Reply/" rel="nofollow noopener">点击了解更多</a></li></ul><p>注意代码 31 行：</p><p><code>const car = new Car({ …req.body })</code></p><p>用到了扩展运算符。<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax" rel="nofollow noopener">点击了解更多</a></p><p>注意代码 42 行：</p><p><code>const { …updateData } = car</code></p><p>使用了 JavaScript 解构赋值和扩展运算符。<a href="https://codeburst.io/use-es2015-object-rest-operator-to-omit-properties-38a3ecffe90" rel="nofollow noopener">点击了解更多</a></p><p>另外，代码还用到了一些标准的 Mongoose 方法来操作数据库。</p><p>可能你已经迫不及待的想要运行你的 API 测试一下了，但是在开始之前，还需要把 controller 连接到 routes，把 routes 连接到 app 上。</p><h2 id="-routes">创建导入 routes</h2><p>同样，在项目根目录下创建 <code>routes</code> 文件夹。在文件夹内创建 <code>index.js</code> 文件，文件代码如下：</p><pre><code class="language-javascript">// Import our Controllers
const carController = require('../controllers/carController')

const routes = [
  {
    method: 'GET',
    url: '/api/cars',
    handler: carController.getCars
  },
  {
    method: 'GET',
    url: '/api/cars/:id',
    handler: carController.getSingleCar
  },
  {
    method: 'POST',
    url: '/api/cars',
    handler: carController.addCar,
    // schema: documentation.addCarSchema
  },
  {
    method: 'PUT',
    url: '/api/cars/:id',
    handler: carController.updateCar
  },
  {
    method: 'DELETE',
    url: '/api/cars/:id',
    handler: carController.deleteCar
  }
]

module.exports = routes
</code></pre><p>在这里我们引入了 controller 并且把每个函数分发到了相应的 routes 上。</p><p>每个 route 都是由 method、url、和 handler 组成，访问路由会调用相应 app 函数。</p><p>上面 routes 里出现的的 <code>:id</code> 是向路由里传递参数的一个常见做法，它允许以下面这种形式传入 id：</p><p><code>http://127.0.0.1:3000/api/cars/5bfe30b46fe410e1cfff2323</code></p><h2 id="-api">文件建立关联，测试 API</h2><p>现在大部分功能都已完成，需要做的只是把他们连接起来，启动 API 服务。导入 routes，在 <code>index.js</code> 文件里添加如下代码：</p><pre><code class="language-javascript">const routes = require(‘./routes’)
</code></pre><p>接下来需要遍历 routes 数组，然后在 Fastify 里面初始化。可以用下面的代码实现，、在 <code>index.js</code> 文件里添加：</p><pre><code class="language-javascript">routes.forEach((route, index) =&gt; {
 fastify.route(route)
})
</code></pre><p>现在准备好测试了！</p><p>API 测试有一个很棒的工具 <a href="https://www.getpostman.com/" rel="nofollow noopener">Postman</a>。我们在request 的 body 里以 raw object 做为参数。</p><p>查询所有 cars:</p><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/optimized/1X/b8ef6416f1451a59f99557a690d914f0232df755_2_690x466.png" class="kg-image" alt="1_YoxRE054Q7qgrAxaCgrzLw" width="600" height="400" loading="lazy"></figure><p>查询指定 car：</p><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/optimized/1X/a4d08c342d764657aebfe9536d192257fb7fc423_2_690x464.png" class="kg-image" alt="1_YoxRE054Q7qgrAxaCgrzLw" width="600" height="400" loading="lazy"></figure><p>添加新 car：</p><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/optimized/1X/1ece5dae70e481415588dcc0feb1c65ba6919db4_2_554x500.png" class="kg-image" alt="1_YoxRE054Q7qgrAxaCgrzLw" width="600" height="400" loading="lazy"></figure><p><em>services 看起来是空的，实际上数据已经添加到了数据库里了</em></p><p>更新 car：</p><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/optimized/1X/b8e1c24297cc2d79d4e4decec34cfedadf557af9_2_556x500.png" class="kg-image" alt="1_YoxRE054Q7qgrAxaCgrzLw" width="600" height="400" loading="lazy"></figure><p>删除 car：</p><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/optimized/1X/18370567d9cdde5da8a352e6b55e192b754b995e_2_690x467.png" class="kg-image" alt="1_YoxRE054Q7qgrAxaCgrzLw" width="600" height="400" loading="lazy"></figure><p>现在一个全功能 API 已具备，还差文档，别怕，用 Swagger 可以方便的生成。</p><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/original/1X/39dcf4afafe6f83e48de459b3be2cef029e8b92f.png" class="kg-image" alt="1_7iaXjYojG6kWxLTZaW1x4Q" width="600" height="400" loading="lazy"></figure><h2 id="-swagger">添加 Swagger</h2><p>现在创建 config 文件夹。在里面创建 <code>swagger.js</code> 文件，文件代码如下：</p><pre><code class="language-javascript">exports.options = {
  routePrefix: '/documentation',
  exposeRoute: true,
  swagger: {
    info: {
      title: 'Fastify API',
      description: 'Building a blazing fast REST API with Node.js, MongoDB, Fastify and Swagger',
      version: '1.0.0'
    },
    externalDocs: {
      url: 'https://swagger.io',
      description: 'Find more info here'
    },
    host: 'localhost',
    schemes: ['http'],
    consumes: ['application/json'],
    produces: ['application/json']
  }
}
</code></pre><p>上面的代码是将要传入到 fastify-swagger 插件的 option object，在<code>index.js</code> 里添加如下代码：</p><pre><code class="language-javascript">// Import Swagger Options
const swagger = require(‘./config/swagger’)
// Register Swagger
fastify.register(require(‘fastify-swagger’), swagger.options)
</code></pre><p>在启动服务之后还需要添加如下代码：</p><pre><code class="language-javascript">...
await fastify.listen(3000)
fastify.swagger()
fastify.log.info(`listening on ${fastify.server.address().port}`)
...
</code></pre><p>如果一切顺利访问 <a href="http://localhost:3000/documentation" rel="nofollow noopener">http://localhost:3000/documentation</a>，效果如下：</p><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/forum/uploads/default/optimized/1X/9ad7aa5a1cc3e2f2212f17121ea926d5fb83c29a_2_690x440.png" class="kg-image" alt="1_HV-5eImCMs7LtiLodTz7CQ" width="600" height="400" loading="lazy"></figure><p>是不是很简单？现在有了随着 API 自动更新的文档，可以任意在 routes 里面添加信息了<a href="https://github.com/fastify/fastify-swagger" rel="nofollow noopener">点击此处阅读更多</a></p><h2 id="--5">接下来</h2><p>现在基本 API 已经成型，可以扩展成能想象的任何应用，有一万种可能。</p><p>接下在的教程里，我们将要集成 GraphQL，最后会集成前端的 Vue.js。</p><p>原文链接：<a href="https://www.freecodecamp.org/news/how-to-build-blazing-fast-rest-apis-with-node-js-mongodb-fastify-and-swagger-114e062db0c9/">How to build blazing fast REST APIs with Node.js, MongoDB, Fastify and Swagger</a>，作者：<a href="https://www.freecodecamp.org/news/author/siegfried/">Siegfried Grimbeek</a></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 三步带你开发一个短链接生成平台 ]]>
                </title>
                <description>
                    <![CDATA[ 前段时间在开发【葡萄城社区】公众号时有一个功能是需要用网页授权认证地址生成二维码，但类似像下面这样的网址url即便是看也觉得很头疼了。 用这个地址生成的二维码也是密密麻麻，虽不影响微信长按扫码，一旦二维码尺寸缩一点点，图片马上就会糊掉，导致摄像头直接扫码会难以识别。 那这种情况下， 我们自然就会想到如果使用短链接减少url的字符，生成的码自然就会变得容易识别了，同时还会使url更美观且易于转发。现在市面上可用的就是微博的t.cn和一些第三方的生成短链接工具，但这两类工具都有一些使用上的问题，例如：t.cn现在的规则是会出现一个中转页不会直接跳转，而第三方的工具因为是一个公共平台，有时可能会因一些不良信息导致整个平台无法访问。 那与其这样，不如我们自己来实现一个短链接平台吧，实现一个短链接平台原理上也非常简单，搞定两部分就行了：1.保存长短链接的对应关系。2.通过短链接查询长连接并重定向。 为了高效，我这使用的是node和mongodb，下面我们就来开始动手吧。 首先，我们先创建一个express工程： express -e demo    change directory ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/shorter-url/</link>
                <guid isPermaLink="false">5f6d4a1f027c3105323f551e</guid>
                
                    <category>
                        <![CDATA[ URL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Willie.ji ]]>
                </dc:creator>
                <pubDate>Fri, 25 Sep 2020 09:22:20 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2020/09/radek-grzybowski-eBRTYyjwpRY-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>前段时间在开发【葡萄城社区】公众号时有一个功能是需要用网页授权认证地址生成二维码，但类似像下面这样的网址url即便是看也觉得很头疼了。</p><figure class="kg-card kg-image-card"><img src="https://chinese.freecodecamp.org/news/content/images/2020/09/image-9.png" class="kg-image" alt="image-9" width="600" height="400" loading="lazy"></figure><p>用这个地址生成的二维码也是密密麻麻，虽不影响微信长按扫码，一旦二维码尺寸缩一点点，图片马上就会糊掉，导致摄像头直接扫码会难以识别。</p><p>那这种情况下， 我们自然就会想到如果使用短链接减少url的字符，生成的码自然就会变得容易识别了，同时还会使url更美观且易于转发。现在市面上可用的就是微博的t.cn和一些第三方的生成短链接工具，但这两类工具都有一些使用上的问题，例如：t.cn现在的规则是会出现一个中转页不会直接跳转，而第三方的工具因为是一个公共平台，有时可能会因一些不良信息导致整个平台无法访问。</p><p>那与其这样，不如我们自己来实现一个短链接平台吧，实现一个短链接平台原理上也非常简单，搞定两部分就行了：1.保存长短链接的对应关系。2.通过短链接查询长连接并重定向。</p><p>为了高效，我这使用的是node和mongodb，下面我们就来开始动手吧。</p><p>首先，我们先创建一个express工程：</p><!--kg-card-begin: markdown--><pre><code>express -e demo

   change directory:
     &gt; cd demo

   install dependencies:
     &gt; npm install

   run the app:
     &gt; SET DEBUG=demo:* &amp; npm start
</code></pre>
<!--kg-card-end: markdown--><p>然后进入demo目录并安装express必要依赖：</p><!--kg-card-begin: markdown--><pre><code>npm install
</code></pre>
<!--kg-card-end: markdown--><p>同时通过 <code>npm</code> 安装我们需要用到的 <code>mongoose</code> 和 <code>shortid</code> 和 <code>body-parser</code>：</p><!--kg-card-begin: markdown--><pre><code>npm install mongoose
npm install shortid
npm install body-parser
</code></pre>
<!--kg-card-end: markdown--><p>下面分别对使用到的这三个包简单说明一下：</p><ul><li>在这个应用中，我们使用了 mongodb，之所以选择它是因为执行高效且低开销，所以执行起来也很高效，不过如果使用其他数据库也是没问题的。这里的<strong>mongoose</strong>就是npm的一个包，主要是为程序提供连接mongodb并增删查改的功能。</li><li>通过使用<strong>shortid</strong>可以生成一个指定字符不重复的编码，便于我们生成类似xxx.com/ngTsfdgh 类似红字部分的编码。</li><li>由于我们生成短链接部分的api使用的是post方法，使用<strong>body-parser</strong>可以多扩展一种body编码类型解析能力。</li></ul><h2 id="-mongodb-">首先设置MongoDB的连接信息</h2><!--kg-card-begin: markdown--><pre><code>module.exports = {
    mongo_base_connection_url: 'mongodb://localhost:27017',
    mongo_db: 'mongodb://localhost:27017/shorturl',
    mongo_options: {
        autoReconnect: true,
        keepAlive: true,
        reconnectTries: 50,
        reconnectInterval: 1000,
        connectTimeoutMS: 5000000,
    }
}
console.log("Connection local mongo db");
</code></pre>
<!--kg-card-end: markdown--><h2 id="-">数据库模型定义</h2><p>因为我们的对应关系是需要通过短链接查询长连接，所以这里我们主要以存储短链接和长连接为主，另外大家也可以根据自己需要添加链接点击统计之类的字段，方便后期统计。</p><!--kg-card-begin: markdown--><pre><code>var mongoose = require('mongoose');
var Schema = mongoose.Schema;
 
var urlSchema = new Schema({
  shortUrl: String,
  longUrl: String
});
 
module.exports = mongoose.model('UrlTable', urlSchema);
</code></pre>
<!--kg-card-end: markdown--><h2 id="-express-">定义express路由</h2><p>因为这个应用我们只有生成和Redirect两个功能，所以这里只有两个页面即可完成所有工作。</p><!--kg-card-begin: markdown--><pre><code>var index = require('./routes/index');
var url = require('./routes/url');
app.use('/', index);
app.use('/url', url);
</code></pre>
<!--kg-card-end: markdown--><h4 id="--1">生成短链接页面</h4><!--kg-card-begin: markdown--><pre><code>const express = require("express");
const router = express.Router();
const shortId = require('shortid');
const UrlTable = require('../models/urltable');
const mongoose = require('mongoose');
var setup = require('../dbconfig/db');
 
router.post('/', function(req, res, next) {
    var params = req.body;
    var url = params.longUrl;
shortId.characters(' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ^*')
    var shortid = shortId.generate();
    var objurl = { shortUrl: shortid, longUrl: url};
    mongoose.connect(setup.mongo_db, setup.mongo_options);
    UrlTable.create(objurl, function (err, objurl) {
      //if (err) console.log(err);
      res.send("http://localhost:3000/" + shortid);
    });
    return;
});
</code></pre>
<!--kg-card-end: markdown--><p>指定生成 <code>shortId</code> 字符的范围并生成：</p><!--kg-card-begin: markdown--><pre><code>shortId.characters('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')

var shortid = shortId.generate();
</code></pre>
<!--kg-card-end: markdown--><p>为数据库构建符合要求的数据模型：</p><!--kg-card-begin: markdown--><pre><code>var objurl = { shortUrl: shortid, longUrl: url};
</code></pre>
<!--kg-card-end: markdown--><p>最后，连接数据库并保存后将短链接结果返回客户端：</p><!--kg-card-begin: markdown--><pre><code>mongoose.connect(setup.mongo_db, setup.mongo_options);
UrlTable.create(objurl, function (err, objurl) {
//if (err) console.log(err);
res.send("http://localhost:3000/" + shortid);
});
</code></pre>
<!--kg-card-end: markdown--><h4 id="--2">短链接跳转页面</h4><!--kg-card-begin: markdown--><pre><code>const express = require("express");
const router = express.Router();
const UrlTable = require('../models/urltable');
const mongoose = require('mongoose');
var setup = require('../dbconfig/db');
 
router.get('/:shortUrl', function (req, res, next) {
    var shortUrl = req.params.shortUrl;
    mongoose.connect(setup.mongo_db, setup.mongo_options);
    UrlTable.findOne({ shortUrl:shortUrl }).then((result) =&gt; {
       //待添加错误处理
    res.redirect(result.longUrl);
    })
});
 
module.exports = router;
</code></pre>
<!--kg-card-end: markdown--><p>这个页面为了便于快速跳转，我们就使用get接收参数，这个页面功能就很简单了，接参查询并跳转。</p><p>接收短链接码：</p><!--kg-card-begin: markdown--><pre><code>var shortUrl = req.params.shortUrl;
</code></pre>
<!--kg-card-end: markdown--><p>连接数据库查询并跳转：</p><!--kg-card-begin: markdown--><pre><code>mongoose.connect(setup.mongo_db, setup.mongo_options);

    UrlTable.findOne({ shortUrl:shortUrl }).then((result) =&gt; {

           //待添加错误处理

      res.redirect(result.longUrl);

 })
</code></pre>
<!--kg-card-end: markdown--><p>后期大家可以对一些错误异常处理，数据统计等做一些增强，这里就不做补充了。</p><p>下面让我们启用应用开始测试吧。</p><h2 id="--3">启动应用并测试</h2><!--kg-card-begin: markdown--><pre><code>npm start
</code></pre>
<!--kg-card-end: markdown--><p>启动后，默认的访问端口为3000，我们首先测试下短链接生成页，这里我们post一个名为longUrl的长链接参数，数据对象为：</p><p>{"longUrl" : "<a href="https://demo.grapecity.com.cn/spreadjs/SpreadJSTutorial/features/tables/basic-table/purejs">https://demo.grapecity.com.cn/spreadjs/SpreadJSTutorial/features/tables/basic-table/purejs</a>"}</p><figure class="kg-card kg-image-card"><img src="https://i.v2ex.co/Kne07O7El.gif" class="kg-image" alt="Kne07O7El" width="600" height="400" loading="lazy"></figure><p>成功升成了如下短链接：</p><p><a href="http://localhost:3000/iGE6ZlDmh">http://localhost:3000/iGE6ZlDmh</a></p><p>我们只要通过访问短链接能正常跳转至保存的长连接即可。</p><figure class="kg-card kg-image-card"><img src="https://i.v2ex.co/mcZ74Zv2l.gif" class="kg-image" alt="mcZ74Zv2l" width="600" height="400" loading="lazy"></figure><p>这样就测试通过了，其实代码量不大，原理也很简单。大家如果自己有较短的域名的话，上线后会让链接变得更短、更美观，这样一个属于我们自己短链接生成平台就开发完成了。下面附上源码，执行npm install 即可自动安装所有依赖，如果大家有问题，可通过评论区告诉我。</p><p><a href="https://files.cnblogs.com/files/powertoolsteam/shorturl.zip">源码下载&gt;&gt;</a></p><p>我们在<a href="https://www.grapecity.com.cn/">葡萄城官网</a>发布更多文章，欢迎阅读！</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
