Mongodb最基础入门教程
<div class="preview html_preview xsj_public"><div style="overflow: hidden; position: absolute; top: 0; height: 1px; width: auto; padding: 0; border: 0; margin: 0; text-align: left; text-indent: 0; text-transform: none; line-height: normal; letter-spacing: normal; word-spacing: normal"> </div>
<div class="xiaoshujiang_element xsj_anchor"></div>
<h2 class="xsj_heading_hash xsj_heading xsj_heading_h2"><span class="xsj_heading_content">Mongodb最基础入门教程</span></h2>
<p class="xsj_paragraph xsj_paragraph_level_0">如果想了解一下redis的入门教程,可以去看一下我的上一篇博客</p>
<p class="xsj_paragraph xsj_paragraph_level_0">Mongodb的安装大家可以参考一下其他博主的博客,这里我就不做介绍了。不过值得注意的是,在Linux版本中如果启动mongodb的时候出现下面这个错误(在windows版本中不会出现下面的问题):</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-shell hljs" data-info="shell">mongod: /usr/lib/libcurl.so.4: version `CURL_OPENSSL_3' not found (required by mongod)</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">原因是因为mongodb启动需要的是<code>libcurl.so.3</code>。在我们安装好<code>libcurl.so.3</code>后,我们可以使用下面的命令打开,其中<strong>LD_PRELOAD</strong>后面跟随的是库的位置。(/data/db文件夹需要赋予可读写的权限)</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-shell hljs" data-info="shell">LD_PRELOAD=/usr/lib/libcurl.so.3 mongod --dbpath /data/dblll</code></pre>
</div>
<div class="xiaoshujiang_element xsj_anchor"></div>
<h3 class="xsj_heading_hash xsj_heading xsj_heading_h3"><span class="xsj_heading_content">简介</span></h3>
<p class="xsj_paragraph xsj_paragraph_level_0">Mongodb是一种非关系性数据库(nosql),关于nosql的介绍可以去看一看菜鸟教程</p>
<blockquote>
<p class="xsj_paragraph xsj_paragraph_level_1">MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。</p>
</blockquote>
<p class="xsj_paragraph xsj_paragraph_level_0">下面是Sql与mongodb的术语对比</p>
<table class="table table-striped table-celled">
<thead>
<tr><th style="text-align: center"><strong>SQL</strong></th><th style="text-align: center"><strong>Mongodb</strong></th></tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">表(Talbe)</td>
<td style="text-align: center">集合(Collection)</td>
</tr>
<tr>
<td style="text-align: center">行(Row)</td>
<td style="text-align: center">文档(Document)</td>
</tr>
<tr>
<td style="text-align: center">列(Col)</td>
<td style="text-align: center">字段(Field)</td>
</tr>
<tr>
<td style="text-align: center">主键(Primary Key)</td>
<td style="text-align: center">对象ID(ObjectId)</td>
</tr>
<tr>
<td style="text-align: center">索引(Index)</td>
<td style="text-align: center">索引(Index)</td>
</tr>
<tr>
<td style="text-align: center">嵌套表(Embeded Table)</td>
<td style="text-align: center">嵌入式文档(Embeded Document)</td>
</tr>
<tr>
<td style="text-align: center">数组(Array)</td>
<td style="text-align: center">数组(Array)</td>
</tr>
</tbody>
</table>
<p class="xsj_paragraph xsj_paragraph_level_0">MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。在Mongodb中,对于插入的格式并没有要求,字段类型可以随意变动。例如,在我创建一个<strong>集合</strong>后,我们可以在这个集合加入下面的数据:</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-json hljs" data-info="json">{
<span class="hljs-attr">"name"</span>:<span class="hljs-string">"this is a name"</span>,
<span class="hljs-attr">"age"</span>:<span class="hljs-number">12</span>
}</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">同样我们也可以在这个数据库插入这样的数据。</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-json hljs" data-info="json">{
<span class="hljs-attr">"name"</span>:<span class="hljs-number">8888</span>,
<span class="hljs-attr">"address"</span>:<span class="hljs-string">"changsha"</span>
}</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">当插入这两个数据后,使用Robo3T数据库可视化工具显示如下:</p>
<p class="xsj_paragraph xsj_paragraph_level_0"> </p>
<div class="story_image_container story_block_image">
<div class="story_image"><img title="" src="https://img2018.cnblogs.com/blog/1439869/201908/1439869-20190824110004971-1777860001.png" alt="" name="imgs/1566547883218.png" data-src="./imgs/1566547883218.png"><br>
<div class="story_image_caption story_image_blank_caption"> </div>
</div>
</div>
<p> </p>
<p class="xsj_paragraph xsj_paragraph_level_0">通过这个我们知道,在向mongodb的同一个表中插入数据的时候,插入的数据字段类型可以不一样,即使是相同的字段数据类型也可以不一样。</p>
<blockquote>
<p class="xsj_paragraph xsj_paragraph_level_1">不过即使mongodb可以这样做,也能够这样做,但是却不是我们应该这样做的理由,我们在设计数据库的时候,应尽量提前考虑好数据库应有的字段,同时每一个字段应该使用同一种数据类型,这样我们才能紧紧的将程序o把握在我们的手里面。</p>
</blockquote>
<div class="xiaoshujiang_element xsj_anchor">
</div>
<h3 class="xsj_heading_hash xsj_heading xsj_heading_h3"><span class="xsj_heading_content">插入数据</span></h3>
<p class="xsj_paragraph xsj_paragraph_level_0">首先我们先创建一个名字为<code>test_data_1</code>的集合。</p>
<div class="xiaoshujiang_element xsj_anchor">
</div>
<h4 class="xsj_heading_hash xsj_heading xsj_heading_h4"><span class="xsj_heading_content">插入一条文档</span></h4>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).insertOne(
{
<span class="hljs-string">"name"</span>:<span class="hljs-number">8888</span>,
<span class="hljs-string">"address"</span>:<span class="hljs-string">"changsha"</span>
}
)</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">当然,将这一条语句写成一行也是没有问题的。其中,Key(也就是上面的name和address)是可以不带引号的,同时对于字符串也可以使用单引号,不过为了统一,在后面统一使用双引号。</p>
<p class="xsj_paragraph xsj_paragraph_level_0">下面是执行这一条数据返回的结果</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">{
<span class="hljs-string">"acknowledged"</span> : <span class="hljs-keyword">true</span>,
<span class="hljs-string">"insertedId"</span> : ObjectId(<span class="hljs-string">"5d5f9e5c0336f9e82b3f9d74"</span>)
}</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">其中<strong>acknowledged</strong>代表数据是否被承认。其中,每一条数据被插入的时候都会返回一个字段“_id”,也就是ObjectId,它是由时间、机器码、进程pid和自增计数器构成的。“_id”始终递增,并绝对不重复。</p>
<div class="xiaoshujiang_element xsj_anchor"></div>
<h4 class="xsj_heading_hash xsj_heading xsj_heading_h4"><span class="xsj_heading_content">插入多个文档</span></h4>
<p class="xsj_paragraph xsj_paragraph_level_0">mongodb也同时支持一次插入多个文档</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).insertMany([
{
<span class="hljs-string">"name"</span>:<span class="hljs-string">"名字1"</span>,
},
{
<span class="hljs-string">"name"</span>:<span class="hljs-string">"名字2"</span>,
},
{
<span class="hljs-string">"address"</span>:<span class="hljs-string">"湖南"</span>
},
]
)</code></pre>
</div>
<blockquote>
<p class="xsj_paragraph xsj_paragraph_level_1">这里我们又可以想一想,我们是否可以使用insertOne实现insertMany的功能?肯定是可以的,但是会造成什么影响呢?我们可以从网络带宽,磁盘IO,机器性能,以及稳定性来考虑。</p>
<p class="xsj_paragraph xsj_paragraph_level_1">在插入相同大小的数据时,使用insertMany的性能要明显好于insertOne,因为insertOne会频繁的调用去插入数据,而insertMany却只会调用一次。如果mangodb数据库与调用者不在同一台机器上,那么性能相差便会更大,因为数据在网络传输的过程中会添加其他的报文。那么插入数据的时候是不是应该将数据全部一次插入呢?也不是!!试想一下,如果插入的数据过多,将磁盘的IO占满了,那么必会对其他程序造成影响。并且,如果在快要插入完所有数据的时候,服务器断电了,那么……所以说,应该合理的选择一次性插入数据库的数量。</p>
</blockquote>
<div class="xiaoshujiang_element xsj_anchor"></div>
<h3 class="xsj_heading_hash xsj_heading xsj_heading_h3"><span class="xsj_heading_content">查询数据</span></h3>
<div class="xiaoshujiang_element xsj_anchor"></div>
<h4 class="xsj_heading_hash xsj_heading xsj_heading_h4"><span class="xsj_heading_content">查询所有数据</span></h4>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).find({})</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">其中{}里面包含的是查询条件,因为是查询所有的数据,所以直接为空就行了,或者省略{}也行。</p>
<div class="xiaoshujiang_element xsj_anchor"></div>
<h4 class="xsj_heading_hash xsj_heading xsj_heading_h4"><span class="xsj_heading_content">查询特定的数据</span></h4>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).find({<span class="hljs-string">"字段1"</span>:<span class="hljs-string">"固定值1"</span>,<span class="hljs-string">"字段2"</span>:<span class="hljs-string">"固定值2"</span>})</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0"> </p>
<div class="story_image_container story_block_image">
<div class="story_image"><img title="" src="https://img2018.cnblogs.com/blog/1439869/201908/1439869-20190824110011023-1196347892.png" alt="" name="imgs/1566553792284.png" data-src="./imgs/1566553792284.png"><br>
<div class="story_image_caption story_image_blank_caption"> </div>
</div>
</div>
<p> </p>
<div class="xiaoshujiang_element xsj_anchor">
</div>
<h4 class="xsj_heading_hash xsj_heading xsj_heading_h4"><span class="xsj_heading_content">查询范围值数据</span></h4>
<p class="xsj_paragraph xsj_paragraph_level_0">下面是查询i范围值的语法,至于操作符,我们后面再说。</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).find(
{
<span class="hljs-string">"字段1"</span>:{<span class="hljs-string">"操作符1"</span>:边界<span class="hljs-number">1</span>,<span class="hljs-string">"操作符2"</span>:边界<span class="hljs-number">2</span>},
<span class="hljs-string">"字段2"</span>:{<span class="hljs-string">"操作符1"</span>:边界<span class="hljs-number">1</span>,<span class="hljs-string">"操作符2"</span>:边界<span class="hljs-number">2</span>}
}
)</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">查询范围值的数据简单,举一个示例:</p>
<p class="xsj_paragraph xsj_paragraph_level_0"> </p>
<div class="story_image_container story_block_image">
<div class="story_image"><img title="" src="https://img2018.cnblogs.com/blog/1439869/201908/1439869-20190824110018265-727973337.png" alt="" name="imgs/1566553999546.png" data-src="./imgs/1566553999546.png"><br>
<div class="story_image_caption story_image_blank_caption"> </div>
</div>
</div>
<p> </p>
<p class="xsj_paragraph xsj_paragraph_level_0">和前面查询特定的数据的方法一样,只不过固定值变成了范围({"$gt":10}代表大于10)。</p>
<p class="xsj_paragraph xsj_paragraph_level_0">下面是范围操作符及其意义:</p>
<table class="table table-striped table-celled">
<thead>
<tr><th style="text-align: center">操作符</th><th style="text-align: center">意义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">$gt</td>
<td style="text-align: center">大于(great than)</td>
</tr>
<tr>
<td style="text-align: center">$gte</td>
<td style="text-align: center">大于等于(great than equal)</td>
</tr>
<tr>
<td style="text-align: center">$lt</td>
<td style="text-align: center">小于(less than)</td>
</tr>
<tr>
<td style="text-align: center">$lte</td>
<td style="text-align: center">小于等于(less than equal)</td>
</tr>
<tr>
<td style="text-align: center">$ne</td>
<td style="text-align: center">不等于(not equal)</td>
</tr>
</tbody>
</table>
<div class="xiaoshujiang_element xsj_anchor">
</div>
<h4 class="xsj_heading_hash xsj_heading xsj_heading_h4"><span class="xsj_heading_content">限定返回字段</span></h4>
<p class="xsj_paragraph xsj_paragraph_level_0">在前面的几张图片中,我们可以看到,使用find操作的时候,返回了所有的字段,那么如果我们并不想要某一些字段的时候,我们应该怎么做呢?</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).find(用于过滤的条件,用于限定的条件)</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">下面便是两个例子:</p>
<ul>
<li>
<p class="xsj_paragraph xsj_paragraph_level_2">去除age<br>
<span class="story_inline_image"><img title="" src="https://img2018.cnblogs.com/blog/1439869/201908/1439869-20190824110024717-146235169.png" alt="" name="imgs/1566555983669.png" data-src="./imgs/1566555983669.png"></span></p>
</li>
<li>
<p class="xsj_paragraph xsj_paragraph_level_2">只返回age<br>
<span class="story_inline_image"><img title="" src="https://img2018.cnblogs.com/blog/1439869/201908/1439869-20190824110031508-2025725080.png" alt="" name="imgs/1566556016586.png" data-src="./imgs/1566556016586.png"></span></p>
</li>
</ul>
<p class="xsj_paragraph xsj_paragraph_level_0">大家会发现,在后面的用于限定的条件中,如果age为1,则返回了<strong>age</strong>和**_id**,如果age为0,则返回了**_id<strong>和</strong>name**。在不考虑_id的情况下,我们可以理解:</p>
<blockquote>
<p class="xsj_paragraph xsj_paragraph_level_1">如果某一个字段被限定为0,则代表该字段不返回(也就是默认其它字段为1),所以其他未被限定的字段则一定会被返回</p>
<p class="xsj_paragraph xsj_paragraph_level_1">如果某一个字段被限定为1,则代表该字段返回(也就是默认其它字段为0),所以其他未被限定的字段则不会被返回</p>
</blockquote>
<p class="xsj_paragraph xsj_paragraph_level_0">_id比较特殊,无论怎样,都要默认返回,当是如果我们真的不需要,那么必须就要把"_id"设置为0。</p>
<div class="xiaoshujiang_element xsj_anchor">
</div>
<h4 class="xsj_heading_hash xsj_heading xsj_heading_h4"><span class="xsj_heading_content">修饰返回结果</span></h4>
<ol>
<li>
<p class="xsj_paragraph xsj_paragraph_level_2">得到数据的条数</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).find({}).count()</code></pre>
</div>
</li>
<li>
<p class="xsj_paragraph xsj_paragraph_level_2">限定返回结果数量</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).find({}).limit(限制返回的数量)</code></pre>
</div>
</li>
<li>
<p class="xsj_paragraph xsj_paragraph_level_2">对结果进行排序</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).find({}).sort({<span class="hljs-string">"字段名"</span>:-<span class="hljs-number">1</span>或者<span class="hljs-number">1</span>})</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_2">其中-1为逆序,1为正序。</p>
</li>
</ol>
<div class="xiaoshujiang_element xsj_anchor"></div>
<h3 class="xsj_heading_hash xsj_heading xsj_heading_h3"><span class="xsj_heading_content">修改数据</span></h3>
<p class="xsj_paragraph xsj_paragraph_level_0">修改数据的前一部分是需要找到数据,然后才能进行修改。同样,在mongodb中,有两种方法修改数据(实际上有很多种)</p>
<ul>
<li>updateOne:只更新第一条符合条件的数据</li>
<li>updateMany:更新所有符合条件的数据</li>
</ul>
<p class="xsj_paragraph xsj_paragraph_level_0">下面介绍<strong>updateMany</strong>的更新数据</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).updateMany(
<span class="hljs-comment">// 下面是查询条件</span>
{
<span class="hljs-string">"字段名1"</span>:<span class="hljs-string">"查找条件1"</span>,<span class="hljs-string">"字段名2"</span>:<span class="hljs-string">"查找条件2"</span>
},
<span class="hljs-comment">// 进行修改</span>
{
<span class="hljs-string">"$set"</span>:{<span class="hljs-string">"字段名"</span>:<span class="hljs-string">"新的数据"</span>,<span class="hljs-string">"字段名"</span>:<span class="hljs-string">"新的数据"</span>}
}
)</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">其中,如果在进行在<em>进行修改</em>的步骤中,如果字段名以前不存在则会进行增添。</p>
<p class="xsj_paragraph xsj_paragraph_level_0">当然,更新数据的内容不可能就这么一点点,但是因为这仅仅是一个基础入门教程,其他的就拜拜吧!想了解更多可以去看看其他的教程。</p>
<div class="xiaoshujiang_element xsj_anchor"></div>
<h3 class="xsj_heading_hash xsj_heading xsj_heading_h3"><span class="xsj_heading_content">删除数据</span></h3>
<p class="xsj_paragraph xsj_paragraph_level_0">删除数据也有两种操作,<strong>deleteOne</strong>和<strong>deleteMany</strong>。和修改数据的情况差不多,一个是删除第一条满足条件的,一个是删除所有满足条件的。</p>
<p class="xsj_paragraph xsj_paragraph_level_0">还是以<strong>deleteMany</strong>来说:</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).deleteMany(
<span class="hljs-comment">// 删除的条件</span>
{
<span class="hljs-string">"字段名1"</span>:<span class="hljs-string">"值"</span>,<span class="hljs-string">"字段名2"</span>:<span class="hljs-string">"值2"</span>
}
)</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">说完简单的mongodb的操作(增删改查)我们现在可以来说一说稍微复杂一点点的操作了。</p>
<div class="xiaoshujiang_element xsj_anchor"></div>
<h3 class="xsj_heading_hash xsj_heading xsj_heading_h3"><span class="xsj_heading_content">数据去重</span></h3>
<p class="xsj_paragraph xsj_paragraph_level_0">在mongodb中进行数据去重是一个很简单的操作。使用<strong>distinct</strong>即可。它可以接收两个参数,第一个参数为需要被去重的字段名,第二个参数是进行去重的条件(去重条件也就是进行查询操作的第一个参数,可以省略)。</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).distinct(去重的字段名,去重的条件)</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">下面举个例子:</p>
<div class="xiaoshujiang_code_container">
<pre><code class="language-java hljs" data-info="java">db.getCollection(<span class="hljs-string">'test_data_1'</span>).distinct(<span class="hljs-string">"name"</span>,{<span class="hljs-string">"age"</span>:{<span class="hljs-string">"$ne"</span>:<span class="hljs-number">10</span>}})</code></pre>
</div>
<p class="xsj_paragraph xsj_paragraph_level_0">这个的含义就是,在age不等于10的条件下对name字段进行去重!那么返回的数据是什么呢?是一个数组,里面是去重后的表中name字段的非重复的数据。</p>
<p class="xsj_paragraph xsj_paragraph_level_0"> </p>
<div class="story_image_container story_block_image">
<div class="story_image"><img title="" src="https://img2018.cnblogs.com/blog/1439869/201908/1439869-20190824110039310-1791354323.png" alt="" name="imgs/1566562244388.png" data-src="./imgs/1566562244388.png"><br>
<div class="story_image_caption story_image_blank_caption"> </div>
</div>
</div>
<p> </p>
<p class="xsj_paragraph xsj_paragraph_level_0">注意:这个去重是对返回值去重,而不是对数据库里面数据去重,也就是说,执行了这个操作,数据库没有发生任何改变。</p>
<p class="xsj_paragraph xsj_paragraph_level_0">在这一章只介绍了mongodb的最最基础的一些东西,本来是想介绍一下Mongodb的其他操作,但是发现其他的操作稍微要复杂一点,所以准备在下一章写。这一章的介绍就介绍到这里,下一篇博客我将介绍一下Mongodb的其他操作。</p>
<div class="xiaoshujiang_element xsj_anchor">
</div>
<h3 class="xsj_heading_hash xsj_heading xsj_heading_h3"><span class="xsj_heading_content">参考</span></h3>
<blockquote>
<p class="xsj_paragraph xsj_paragraph_level_1">参考书籍:《左手Mongodb,右手Redis》</p>
<p class="xsj_paragraph xsj_paragraph_level_1">菜鸟教程:https://www.runoob.com/mongodb/mongodb-tutorial.html</p>
</blockquote>
</div>
</div>
<div id="MySignature" role="contentinfo">
<div id="AllanboltSignature">
<div id="PSignature" style="border-top: #e0e0e0 1px dashed; border-right: #e0e0e0 1px dashed; border-bottom: #e0e0e0 1px dashed; border-left: #e0e0e0 1px dashed;
padding-top: 10px;padding-right: 10px;padding-bottom: 10px;padding-left: 60px;
background: url(https://pic.cnblogs.com/face/1439869/20181028130953.png) #e5f1f4 no-repeat 1% 50%;
font-family: 微软雅黑; font-size:11px;">
<br /> 作者: 渣渣辉啊
<br /> 出处:https://www.cnblogs.com/xiaohuiduan/p/11403891.html
<div><h3>邮箱📫:xiaohuiduan@hunnu.edu.cn</h3></div>
</div>
</div><br><br>
来源:https://www.cnblogs.com/xiaohuiduan/p/11403891.html
頁:
[1]