-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
158 lines (75 loc) · 97.1 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>mongoDB学习笔记</title>
<link href="/2022/08/11/mongoDB%E7%AC%94%E8%AE%B0/"/>
<url>/2022/08/11/mongoDB%E7%AC%94%E8%AE%B0/</url>
<content type="html"><![CDATA[<p>MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。</p><h4 id="一、数据库相关"><a href="#一、数据库相关" class="headerlink" title="一、数据库相关"></a>一、数据库相关</h4><h5 id="1-连接"><a href="#1-连接" class="headerlink" title="1.连接"></a>1.连接</h5><p>(1)完整</p><pre><code>mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]</code></pre><p>(2)使用默认端口</p><pre><code>mongodb://localhost</code></pre><p>(3)使用shell</p><pre><code>mongo</code></pre><h5 id="2-查询数据库"><a href="#2-查询数据库" class="headerlink" title="2.查询数据库"></a>2.查询数据库</h5><p>(1)查询所有数据库</p><pre><code>show dbs</code></pre><h5 id="3-创建数据库"><a href="#3-创建数据库" class="headerlink" title="3.创建数据库"></a>3.创建数据库</h5><pre><code>use database_name</code></pre><p>如果数据库不存在,则创建并切换到该数据库,存在则切换到该数据库。并且刚创建的数据库在没有插入数据的时候是不会显示的出来的,需要插入数据才能显示。</p><h5 id="4-删除数据库"><a href="#4-删除数据库" class="headerlink" title="4.删除数据库"></a>4.删除数据库</h5><p>先切换到指定数据库,然后执行以下命令</p><pre><code>#删除 test数据库use testdb.dropDatabase()</code></pre><h4 id="二、集合相关"><a href="#二、集合相关" class="headerlink" title="二、集合相关"></a>二、集合相关</h4><h5 id="1-创建集合"><a href="#1-创建集合" class="headerlink" title="1.创建集合"></a>1.创建集合</h5><p>切换到指定数据库,然后执行如下命令</p><pre><code>db.createCollection(name, options)</code></pre><p>说明:</p><p>name 要创建的集合名称,可选参数,指定有关内存大小及索引的选项</p><p>options参数:capped如果为true则创建固定集合(有着固定大小的集合);size为固定集合指定一个最大值,如果capped为true需要指定该字段;max 指定固定集合中包含文档的最大数量,size代表文档的最大占用空间。并且插入文档会自动创建集合。</p><pre><code>#创建有参数的集合db.creatCollection("test", { capped : true, size : 1024, max : 1000})#直接插入文档创建集合db.test.insert({"name" : "oyc"})</code></pre><h5 id="2-查看所有集合"><a href="#2-查看所有集合" class="headerlink" title="2.查看所有集合"></a>2.查看所有集合</h5><p>先切换到指定数据库,然后执行如下命令</p><pre><code>use testshow collections</code></pre><h5 id="3-删除集合"><a href="#3-删除集合" class="headerlink" title="3.删除集合"></a>3.删除集合</h5><pre><code>db.COLLECTION_NAME.drop()</code></pre><p>成功删除则返回true,否则返回false </p><h4 id="三、文档相关"><a href="#三、文档相关" class="headerlink" title="三、文档相关"></a>三、文档相关</h4><h5 id="1-插入文档"><a href="#1-插入文档" class="headerlink" title="1.插入文档"></a>1.插入文档</h5><p>使用insert()或insertOne()或insertMany()方法插入文档</p><pre><code>db.COLLECTION_NAME.insert(document)</code></pre><pre><code>插入单条数据db.collection.insertOne( <document>, { writeConcern: <document> })插入多条数据 db.collection.insertMany( [ <document 1> , <document 2>, ... ], { writeConcern: <document>, ordered: <boolean> })document: 要写入的文档writeConcern:写入策略,默认为1,即要求默认写操作,0是不要求ordered:是否按照顺序写入,默认为true,按照顺序写入</code></pre><h5 id="2-查询文档"><a href="#2-查询文档" class="headerlink" title="2.查询文档"></a>2.查询文档</h5><pre><code>db.COLLECTION_NAME.find(query, projection)query :可选,使用查询操作符指定查询条件projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。pretty()以格式化方法显示文档</code></pre><h5 id="3-更新文档"><a href="#3-更新文档" class="headerlink" title="3.更新文档"></a>3.更新文档</h5><p>使用update()和save()方法来更新集合中的文档</p><p>(1)update()方法</p><pre><code>db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> })db.collection.updata({"name":"oyc"},{$set:{"age":21}})参数说明:query : update的查询条件,类似sql update查询内where后面的。update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。writeConcern :可选,抛出异常的级别。</code></pre><p>(2)save()方法</p><p>save() 方法通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插入。</p><pre><code>db.collection.save( <document>, { writeConcern: <document> })#将_id主键为ObjectId("123")的文档进行保存,如果存在就更新,如果不存在就创建db.collection.save({"_id":ObjectId("123"),"name":"oyc123"})参数说明:document : 文档数据。writeConcern :可选,抛出异常的级别。</code></pre><h5 id="4-删除文档"><a href="#4-删除文档" class="headerlink" title="4.删除文档"></a>4.删除文档</h5><pre><code>db.collection.remove( <query>, <justOne>)参数说明:db.collection.remove({"name":"oyc"})query :(可选)删除的文档的条件。justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。</code></pre><h4 id="四、条件操作符"><a href="#四、条件操作符" class="headerlink" title="四、条件操作符"></a>四、条件操作符</h4><pre><code>1.大于(>): $gtdb.collection2.find({age : {$gt : 30}})2.大于等于(>=): $gtedb.collection2.find({age : {$gte : 30}})3.小于(<):$ltdb.collection2.find({age : {$lt : 20}})4.小于等于(<=):$ltedb.collection2.find({age : {$lte : 20}})5.$lt 和 $gtdb.collection2.find({age : {$gt : 30, $lt : 60,}})</code></pre><h4 id="五、-type操作符"><a href="#五、-type操作符" class="headerlink" title="五、$type操作符"></a>五、$type操作符</h4><p>MongoDB 中可以使用的类型如下表所示:</p><table><thead><tr><th align="center">类型</th><th align="center">数字</th><th align="center">备注</th></tr></thead><tbody><tr><td align="center">Double</td><td align="center">1</td><td align="center"></td></tr><tr><td align="center">String</td><td align="center">2</td><td align="center"></td></tr><tr><td align="center">Object</td><td align="center">3</td><td align="center"></td></tr><tr><td align="center">Array</td><td align="center">4</td><td align="center"></td></tr><tr><td align="center">Binary data</td><td align="center">5</td><td align="center"></td></tr><tr><td align="center">Undefined</td><td align="center">6</td><td align="center">已废弃</td></tr><tr><td align="center">ObjectId</td><td align="center">7</td><td align="center"></td></tr><tr><td align="center">Boolean</td><td align="center">8</td><td align="center"></td></tr><tr><td align="center">Date</td><td align="center">9</td><td align="center"></td></tr><tr><td align="center">Null</td><td align="center">10</td><td align="center"></td></tr><tr><td align="center">RegularExpression</td><td align="center">11</td><td align="center"></td></tr><tr><td align="center">JavaScript</td><td align="center">13</td><td align="center"></td></tr><tr><td align="center">Symbol</td><td align="center">14</td><td align="center"></td></tr><tr><td align="center">JavaScript(with scope)</td><td align="center">15</td><td align="center"></td></tr><tr><td align="center">32 bit integer</td><td align="center">16</td><td align="center"></td></tr><tr><td align="center">Timestamp</td><td align="center">17</td><td align="center"></td></tr><tr><td align="center">64 bit integer</td><td align="center">18</td><td align="center"></td></tr><tr><td align="center">Min key</td><td align="center">255</td><td align="center">Query with -1</td></tr><tr><td align="center">Max key</td><td align="center">127</td><td align="center"></td></tr><tr><td align="center"></td><td align="center"></td><td align="center"></td></tr></tbody></table><pre><code>db.collection2.find({"name" : {$type :2}})db.collection2.find({"name" : {$type :'string'}})</code></pre><h4 id="六、MongoDB-Limit与Skip方法"><a href="#六、MongoDB-Limit与Skip方法" class="headerlink" title="六、MongoDB Limit与Skip方法"></a>六、MongoDB Limit与Skip方法</h4><h5 id="1-limit-读取记录的条数"><a href="#1-limit-读取记录的条数" class="headerlink" title="1.limit()读取记录的条数"></a>1.limit()读取记录的条数</h5><pre><code>#限制查询出来的文档中只显示一个文档db.COLLECTION_NAME.find().limit(NUMBER)</code></pre><h5 id="2-skip-跳过的记录条数"><a href="#2-skip-跳过的记录条数" class="headerlink" title="2.skip()跳过的记录条数"></a>2.skip()跳过的记录条数</h5><pre><code>#在查询出来的文档中,跳过number1个文档后显示number2个文档。db.COLLECTION_NAME.find().limit(NUMBER2).skip(NUMBER1)</code></pre><h4 id="七、排序"><a href="#七、排序" class="headerlink" title="七、排序"></a>七、排序</h4><p>sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。</p><h5 id="1-升序排序"><a href="#1-升序排序" class="headerlink" title="1.升序排序"></a>1.升序排序</h5><pre><code>db.COLLECTION_NAME.find().sort({KEY:1}) </code></pre><h5 id="2-降序排序"><a href="#2-降序排序" class="headerlink" title="2.降序排序"></a>2.降序排序</h5><pre><code>db.COLLECTION_NAME.find().sort({KEY:-1})</code></pre><h4 id="八、索引"><a href="#八、索引" class="headerlink" title="八、索引"></a>八、索引</h4><p>使用createIndex()方法创建索引</p><pre><code>db.collection.createIndex(keys, options)</code></pre><p>语法中 key值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。</p><p>createIndex() 接收可选参数,可选参数列表如下:</p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202208101450358.png" > </sapn> </p><h4 id="九、聚合"><a href="#九、聚合" class="headerlink" title="九、聚合"></a>九、聚合</h4><h5 id="1-聚合"><a href="#1-聚合" class="headerlink" title="1.聚合"></a>1.聚合</h5><p>聚合主要用来处理数据(平均值、求和等),并返回计算结果。</p><pre><code>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)</code></pre><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202208101452917.png" > </sapn> </p><h5 id="2-聚合管道"><a href="#2-聚合管道" class="headerlink" title="2.聚合管道"></a>2.聚合管道</h5><p>聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。</p><p>表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。</p><p>聚合框架中常用的几个操作:</p><ul><li><p>$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。</p></li><li><p>$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。</p></li><li><p>$limit:用来限制MongoDB聚合管道返回的文档数。</p></li><li><p>$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。</p></li><li><p>$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。</p></li><li><p>$group:将集合中的文档分组,可用于统计结果。</p></li><li><p>$sort:将输入文档排序后输出。</p></li><li><p>$geoNear:输出接近某一地理位置的有序文档。</p></li></ul><p>统计colection2集合中记录条数</p><pre><code>db.collection2.aggregate( [ { $group: { _id: null, count: { $sum: 1 } } }] )</code></pre><p>统计collection2集合age的和</p><pre><code>db.collection2.aggregate( [ { $group: { _id: null, total: { $sum: "$age" } } }] )</code></pre><p>统计collection2集合中age>=10且=30的age的和</p><pre><code>db.collection2.aggregate( [ { $match : { age : { $gte : 10, $lte : 30 } } }, { $group: { _id: null, total: { $sum: "$age" } } }] )</code></pre><h4 id="十、复制"><a href="#十、复制" class="headerlink" title="十、复制"></a>十、复制</h4><h5 id="1-复制:"><a href="#1-复制:" class="headerlink" title="1.复制:"></a>1.复制:</h5><p>复制是将数据同步在多个服务器的过程</p><h5 id="2-复制原理"><a href="#2-复制原理" class="headerlink" title="2.复制原理"></a>2.复制原理</h5><p><strong>MongoDB复制至少需要2个节点,其中1个是主节点</strong>,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。常见的搭配的方式:一主一从、一主多从。</p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202208101503640.png" > </sapn> </p><p>以上结构图中,客户端从主节点读取数据,在客户端写入数据到主节点时,主节点与从节点交互保证数据一致性。</p><h4 id="十一、分片"><a href="#十一、分片" class="headerlink" title="十一、分片"></a>十一、分片</h4><h5 id="1-需求"><a href="#1-需求" class="headerlink" title="1.需求"></a>1.需求</h5><p>当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。这时,我么就可以在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。</p><h5 id="2-为什么使用分片"><a href="#2-为什么使用分片" class="headerlink" title="2.为什么使用分片"></a>2.为什么使用分片</h5><ul><li><p>复制所有的写入操作到主节点</p></li><li><p>延迟的敏感数据会在主节点上查询</p></li><li><p>单个副本集限制在12个节点</p></li><li><p>当请求量巨大时出现内存不足</p></li><li><p>本地磁盘不足</p></li><li><p>垂直扩展价格昂贵</p></li></ul><h5 id="3-MongoDB分片"><a href="#3-MongoDB分片" class="headerlink" title="3.MongoDB分片"></a>3.MongoDB分片</h5><p>分片集群结构</p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202208101506410.png" > </sapn> </p><ul><li><p>Shard:用于存储实际的数据块,实际生产环境中一个Shard Server角色可由几台机器组成一个replica set承担,防止单点故障</p></li><li><p>Config Server:mongod实例,存储整个ClusterMetadata,其中包括chunk信息</p></li><li><p>Query Routers::前端路由,客户端由此接入,且整个集群看上去像单一数据库,前端应用可以透明使用。</p></li></ul><h4 id="十二、备份与还原"><a href="#十二、备份与还原" class="headerlink" title="十二、备份与还原"></a>十二、备份与还原</h4><pre><code>mongodump -h dbhost -d dbname -o dbdirectory-h:MongoDB 所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017-d:需要备份的数据库实例,例如:test-o:备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。</code></pre><p>mongodump 命令可选参数列表如下所示:</p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202208101510128.png" > </sapn> </p><pre><code>mongodump</code></pre><p> 执行以上命令后,客户端会连接到ip为 127.0.0.1 端口号为 27017 的MongoDB服务上,并备份所有数据到 bin/dump/ 目录中。</p><h4 id="十三、监控"><a href="#十三、监控" class="headerlink" title="十三、监控"></a>十三、监控</h4><p>了解MongoDB的运行情况,并查看MongoDB的性能。这样在大流量得情况下可以很好的应对并保证MongoDB正常运作。MongoDB中提供了mongostat 和 mongotop 两个命令来监控MongoDB的运行情况。</p><h5 id="1-mongostat-命令"><a href="#1-mongostat-命令" class="headerlink" title="1.mongostat 命令"></a>1.mongostat 命令</h5><p>mongostat是mongodb自带的状态检测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。如果你发现数据库突然变慢或者有其他问题的话,你第一手的操作就考虑采用mongostat来查看mongo的状态。</p><p>启动你的Mongod服务,进入到你安装的MongoDB目录下的bin目录, 然后输入mongostat命令。配置过环境路径的就直接命令行输入mongostat。</p><h5 id="2-mongotop-命令"><a href="#2-mongotop-命令" class="headerlink" title="2.mongotop 命令"></a>2.mongotop 命令</h5><p>mongotop也是mongodb下的一个内置工具,mongotop提供了一个方法,用来跟踪一个MongoDB的实例,查看哪些大量的时间花费在读取和写入数据。 mongotop提供每个集合的水平的统计数据。默认情况下,mongotop返回值的每一秒。</p><p>启动你的Mongod服务,进入到你安装的MongoDB目录下的bin目录, 然后输入mongotop命令,配置过环境路径的就直接命令行输入mongotop。</p><h4 id="十四、MongoDB高级"><a href="#十四、MongoDB高级" class="headerlink" title="十四、MongoDB高级"></a>十四、MongoDB高级</h4><h5 id="1-关系"><a href="#1-关系" class="headerlink" title="1.关系"></a>1.关系</h5><p>MongoDB 中的关系可以是:</p><ul><li>1:1 (1对1)</li><li>1: N (1对多)</li><li>N: 1 (多对1)</li><li>N: N (多对多)</li></ul><p>下面以用户的地址为例</p><p>(1)嵌入式关系</p><p>缺点:如果用户和用户地址在不断增加,数据量不断变大,会影响读写性能</p><pre><code>{ "_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address": [ { "building": "22 A, Indiana Apt", "pincode": 123456, "city": "Los Angeles", "state": "California" }, { "building": "170 A, Acropolis Apt", "pincode": 456789, "city": "Chicago", "state": "Illinois" }]} </code></pre><p>查询</p><pre><code>db.users.findOne({"name":"Tom Benzamin"},{"address":1})</code></pre><p>(2)引用关系</p><pre><code>{ "_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address_ids": [ ObjectId("52ffc4a5d85242602e000000"), ObjectId("52ffc4a5d85242602e000001") ]}</code></pre><p>这种方法需要两次查询,第一次查询用户地址的对象id(ObjectId),第二次通过查询的id获取用户的详细地址信息</p><pre><code>var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1})var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})</code></pre><h5 id="2-查询分析"><a href="#2-查询分析" class="headerlink" title="2.查询分析"></a>2.查询分析</h5><p>查询分析常用函数explain()和hint()</p><p>(1)explain 操作提供了查询信息,使用索引及查询统计等。有利于我们对索引的优化。</p><p>创建gender和user_name的索引</p><pre><code>db.users.ensureIndex({gender:1,user_name:1})</code></pre><p>使用explaing </p><pre><code>db.users.find({gender:"M"},{user_name:1,_id:0}).explain()</code></pre><p>返回结果如下:</p><pre><code>{ "cursor" : "BtreeCursor gender_1_user_name_1", "isMultiKey" : false, "n" : 1, "nscannedObjects" : 0, "nscanned" : 1, "nscannedObjectsAllPlans" : 0, "nscannedAllPlans" : 1, "scanAndOrder" : false, "indexOnly" : true, "nYields" : 0, "nChunkSkips" : 0, "millis" : 0, "indexBounds" : { "gender" : [ [ "M", "M" ] ], "user_name" : [ [ { "$minElement" : 1 }, { "$maxElement" : 1 } ] ] }}</code></pre><ul><li><p>indexOnly: 字段为 true ,表示我们使用了索引。</p></li><li><p>cursor:因为这个查询使用了索引,MongoDB 中索引存储在B树结构中,所以这是也使用了 BtreeCursor 类型的游标。如果没有使用索引,游标的类型是 BasicCursor。这个键还会给出你所使用的索引的名称,你通过这个名称可以查看当前数据库下的system.indexes集合(系统自动创建,由于存储索引信息,这个稍微会提到)来得到索引的详细信息。</p></li><li><p>n:当前查询返回的文档数量。</p></li><li><p>nscanned/nscannedObjects:表明当前这次查询一共扫描了集合中多少个文档,我们的目的是,让这个数值和返回文档的数量越接近越好。</p></li><li><p>millis:当前查询所需时间,毫秒数。</p></li><li><p>indexBounds:当前查询具体使用的索引。</p></li></ul><p>(2)使用 hint()</p><p>可以使用 hint 来强制 MongoDB 使用一个指定的索引。<strong>这种方法某些情形下会提升性能</strong>。 一个有索引的 collection 并且执行一个多字段的查询(一些字段已经索引了)。</p><p>如下查询实例指定了使用 <code>gender</code> 和<code> user_name</code> 索引字段来查询:</p><pre><code>db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1})</code></pre><p>可以使用 explain() 函数来分析以上查询:</p><pre><code>db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1}).explain()</code></pre><h5 id="3-原子操作"><a href="#3-原子操作" class="headerlink" title="3.原子操作"></a>3.原子操作</h5><p>mongodb不支持事务,但是提供了许多原子操作,比如文档的保存,修改,删除等,都是原子操作。所谓原子操作就是要么这个文档保存到Mongodb,要么没有保存到Mongodb,不会出现查询到的文档没有保存完整的情况。原子操作命令如下:</p><p>(1)$set 用来指定一个键并更新键值,若键不存在并创建。</p><pre><code>{ $set : { field : value } }</code></pre><p>(2)$unset 用来删除一个键。</p><pre><code>{ $unset : { field : 1} }</code></pre><p>(3)$inc 可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。</p><pre><code>{ $inc : { field : value } }</code></pre><p>(4)$push 把value追加到field里面去,field一定要是数组类型才行,如果field不存在,会新增一个数组类型加进去。</p><pre><code>{ $push : { field : value } }</code></pre><p>(5)$pushAll 同$push,只是一次可以追加多个值到一个数组字段内。</p><pre><code>{ $pushAll : { field : value_array } }</code></pre><p>(6)$pull 从数组field内删除一个等于value值。</p><pre><code>{ $pull : { field : _value } }</code></pre><p>(7)$addToSet 增加一个值到数组内,而且只有当这个值不在数组内才增加。</p><p>(8)$pop 删除数组的第一个或最后一个元素</p><pre><code>{ $pop : { field : 1 } }</code></pre><p>(9)$rename 修改字段名称</p><pre><code>{ $rename : { old_field_name : new_field_name } }</code></pre><p>(10)$bit 位操作,integer类型</p><pre><code>{$bit : { field : {and : 5}}}</code></pre><h5 id="4-高级索引"><a href="#4-高级索引" class="headerlink" title="4.高级索引"></a>4.高级索引</h5><pre><code>{ "address": { "city": "Los Angeles", "state": "California", "pincode": "123" }, "tags": [ "music", "cricket", "blogs" ], "name": "Tom Benzamin"}</code></pre><p>(1)索引数组</p><p>假设我们基于标签来检索用户,为此我们需要对集合中的数组 tags 建立索引。在数组中创建索引,需要对数组中的每个字段依次建立索引。所以在我们为数组 tags 创建索引时,会为 music、cricket、blogs三个值建立单独的索引</p><p>创建数组索引</p><pre><code>db.users.ensureIndex({"tags":1})</code></pre><p> 检索集合的 tags 字段</p><pre><code>db.users.find({tags:"cricket"})</code></pre><p>(2)索引子文档字段</p><p>假设我们需要通过city、state、pincode字段来检索文档,由于这些字段是子文档的字段,所以我们需要对子文档建立索引。</p><p>创建索引</p><pre><code>db.users.ensureIndex({"address.city":1,"address.state":1,"address.pincode":1})</code></pre><p>检索数据</p><pre><code>db.users.find({"address.city":"Los Angeles","address.state":"California","address.pincode":"123"})</code></pre><p>(3)索引最大范围</p><p>集合中索引不能超过64个<br>索引名的长度不能超过128个字符<br>一个复合索引最多可以有31个字段</p><h5 id="5-ObjectId"><a href="#5-ObjectId" class="headerlink" title="5.ObjectId"></a>5.ObjectId</h5><p>ObjectId 是一个12字节 BSON 类型数据,有以下格式:</p><ul><li><p>前4个字节表示时间戳</p></li><li><p>接下来的3个字节是机器标识码</p></li><li><p>紧接的两个字节由进程id组成(PID)</p></li><li><p>最后三个字节是随机数。</p></li></ul><p>MongoDB中存储的文档必须有一个”_id”键。这个键的值可以是任何类型的,默认是个ObjectId对象。在一个集合里面,每个文档都有唯一的”_id”值,来确保集合里面每个文档都能被唯一标识。MongoDB采用ObjectId,而不是其他比较常规的做法(比如自动增加的主键)的主要原因,因为在多个 服务器上同步自动增加主键值既费力还费时。</p><p>(1)创建新的ObjectId</p><pre><code>newObjectId = ObjectId()</code></pre><p>(2)创建文档的时间戳</p><pre><code>ObjectId("5349b4ddd2781d08c09890f4").getTimestamp()</code></pre><p>(3)ObjectId 转换为字符串</p><pre><code>new ObjectId().str</code></pre><h5 id="6-mapReduce"><a href="#6-mapReduce" class="headerlink" title="6.mapReduce"></a>6.mapReduce</h5><p>Map-Reduce是一种计算模型,简单地说就是将大量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(Reduce)。</p><p>基本语法:</p><pre><code>db.collection.mapReduce( function() {emit(key,value);}, //map 函数 function(key,values) {return reduceFunction}, //reduce 函数 { out: collection, query: document, sort: document, limit: number })</code></pre><p>使用 MapReduce 要实现两个函数 Map 函数和 Reduce 函数,Map 函数调用 emit(key, value), 遍历 collection 中所有的记录, 将 key 与 value 传递给 Reduce 函数进行处理。</p><p>Map 函数必须调用 emit(key, value) 返回键值对。</p><p>参数说明:</p><ul><li>map :映射函数 (生成键值对序列,作为 reduce 函数参数)。</li><li>reduce 统计函数,reduce函数的任务就是将key-values变成key-value,也就是把values数组变成一个单一的值value。。</li><li>out 统计结果存放集合 (不指定则使用临时集合,在客户端断开后自动删除)。</li><li>query 一个筛选条件,只有满足条件的文档才会调用map函数。(query。limit,sort可以随意组合)</li><li>sort 和limit结合的sort排序参数(也是在发往map函数前给文档排序),可以优化分组机制</li><li>limit 发往map函数的文档数量的上限(要是没有limit,单独使用sort的用处不大)</li></ul><p>返回结果参数说明:</p><ul><li>result:储存结果的collection的名字,这是个临时集合,MapReduce的连接关闭后自动就被删除了。</li><li>timeMillis:执行花费的时间,毫秒为单位</li><li>input:满足条件被发送到map函数的文档个数</li><li>emit:在map函数中emit被调用的次数,也就是所有集合中的数据总量</li><li>ouput:结果集合中的文档个数(count对调试非常有帮助)</li><li>ok:是否成功,成功为1</li><li>err:如果失败,这里可以有失败原因,不过从经验上来看,原因比较模糊,作用不大</li></ul><h5 id="7-全文索引"><a href="#7-全文索引" class="headerlink" title="7.全文索引"></a>7.全文索引</h5><p>全文检索对每一个词建立一个索引,指明该词在文章中出现的位置和次数,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。类似于通过字典中检索字表查字的过程</p><p>(1)创建全文索引</p><pre><code>db.posts.ensureIndex({post_text:"text"})</code></pre><p>(2)使用全文索引</p><pre><code>db.posts.find({$text:{$search:"mongodb"}})</code></pre><p>(3)删除索引</p><pre><code>db.posts.dropIndex("post_text_text")</code></pre><h5 id="8-正则表达式"><a href="#8-正则表达式" class="headerlink" title="8.正则表达式"></a>8.正则表达式</h5><p>使用 $regex 操作符来设置匹配字符串的正则表达式。</p><p>(1)使用正则表达式</p><pre><code>db.posts.find({post_text:{$regex:"runoob"}})</code></pre><p>(2)不区分大小写</p><p>如果检索需要不区分大小写,我们可以设置 $options 为 $i。</p><h5 id="9-GridFS"><a href="#9-GridFS" class="headerlink" title="9.GridFS"></a>9.GridFS</h5><p>GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。</p><p>GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中。</p><p>GridFS 可以更好的存储大于16M的文件。</p><p>GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。</p><p>GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。</p><p>每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。</p><p>以下是简单的 fs.files 集合文档:</p><pre><code>{ "filename": "test.txt", "chunkSize": NumberInt(261120), "uploadDate": ISODate("2014-04-13T11:32:33.557Z"), "md5": "7b762939321e146569b07f72c62cca4f", "length": NumberInt(646)}</code></pre><p>以下是简单的 fs.chunks 集合文档:</p><pre><code>{ "files_id": ObjectId("534a75d19f54bfec8a2fe44b"), "n": NumberInt(0), "data": "Mongo Binary Data"}</code></pre><p>GridFS 添加文件<br>现在我们使用 GridFS 的 put 命令来存储 mp3 文件。 调用 MongoDB 安装目录下bin的 mongofiles.exe工具。</p><p>打开命令提示符,进入到MongoDB的安装目录的bin目录中,找到mongofiles.exe,并输入下面的代码:</p><pre><code>mongofiles.exe -d gridfs put song.mp3</code></pre><p>-d gridfs 指定存储文件的数据库名称,如果不存在该数据库,MongoDB会自动创建。如果不存在该数据库,MongoDB会自动创建。Song.mp3 是音频文件名。</p><p>使用以下命令来查看数据库中文件的文档:</p><pre><code>db.fs.files.find()</code></pre><p>以上命令执行后返回以下文档数据:</p><pre><code>{ _id: ObjectId('534a811bf8b4aa4d33fdf94d'), filename: "song.mp3", chunkSize: 261120, uploadDate: new Date(1397391643474), md5: "e4f53379c909f7bed2e9d631e15c1c41", length: 10401959 }</code></pre><p>我们可以看到 fs.chunks 集合中所有的区块,以下我们得到了文件的 _id 值,我们可以根据这个 _id 获取区块(chunk)的数据:</p><pre><code>db.fs.chunks.find({files_id:ObjectId('534a811bf8b4aa4d33fdf94d')})</code></pre><h5 id="10-自动增长"><a href="#10-自动增长" class="headerlink" title="10.自动增长"></a>10.自动增长</h5><p>sequence_value 字段是序列通过自动增长后的一个值。</p><pre><code>db.counters.insert({_id:"productid",sequence_value:0})</code></pre>]]></content>
</entry>
<entry>
<title>Shell学习.md</title>
<link href="/2022/08/02/Shell%E5%AD%A6%E4%B9%A0/"/>
<url>/2022/08/02/Shell%E5%AD%A6%E4%B9%A0/</url>
<content type="html"><![CDATA[<h4 id="了解:"><a href="#了解:" class="headerlink" title="了解:"></a>了解:</h4><ul><li>shell是帮助应用程序操作Linux内核的工具。</li><li>Shell解析器有很多(bash,zsh…),但是默认的是bash(mac默认zsh),sh的软连接是bash。</li><li>shell文件的开头要指定解析器,格式为:<code>#!/bin/bash</code></li></ul><h4 id="基本变量语法:"><a href="#基本变量语法:" class="headerlink" title="基本变量语法:"></a>基本变量语法:</h4><ul><li>定义变量,<code>A=2</code>,注意这里的等号两边没有空格</li><li>撤销变量:unset A</li><li>声明静态只读变量:readonly A=3,注意静态只读变量不能撤销</li></ul><h4 id="变量命名规则:"><a href="#变量命名规则:" class="headerlink" title="变量命名规则:"></a>变量命名规则:</h4><ul><li>和大部分语言中一样,由字母、数字和下划线组成,但是不能由数字开头,环境变量名称建议大写(如:$HOME)</li><li>等号两侧不能有空格</li><li>在bash解释器中,变量默认都是字符串类型,无法直接进行数值运算。</li><li>变量的值如果有空格需要用双引号或者单引号扩起来。</li><li>把变量提升为全局变量:export 变量名(export GOPATH)</li></ul><h4 id="特殊变量:"><a href="#特殊变量:" class="headerlink" title="特殊变量:"></a><strong>特殊变量</strong>:</h4><ul><li>**<code>$n</code>**:n代表数字,其中$0为当前shell脚本名称,1-9为当前命令后面添加的参数,十以上的参数要用大括号表示,如${10}。</li><li>**<code>$#</code>**:代表当前所有的参数个数,没有参数则为0。</li><li>**<code>$*与$@</code><strong>:两个都是获取当前所有的参数列表,只不过</strong><code>*</code><strong>号是一次性获取,把所有的参数看成一个整体,而</strong>@**是一个个的获取,区分对待。</li><li>**<code>$?</code>**:返回一个数值,如果为0则表示上一条shell语句执行成功,如果不为0那么代表执行失败。</li></ul><h4 id="‘,“,-96-符号区分"><a href="#‘,“,-96-符号区分" class="headerlink" title="‘,“,`符号区分"></a>‘,“,`符号区分</h4><p>在bash中“空格”是一种很特殊的字符,比如在bash中这样定义<code>str=this is String</code>,这样就会报错,为了避免出错就得使用单引号’’和双引号””。</p><p>单引号’’,双引号””的区别是单引号’’剥夺了所有字符的特殊含义,单引号’’内就变成了单纯的字符。双引号””则对于双引号””内的参数替换($)和命令替换(``)是个例外。</p><p>比如说 :</p><pre><code>str="hello" echo '$str'</code></pre><p>结果就是$str,但是改成双引号的话,<code>echo "$str"</code>,结果就是hello</p><p>``:反引号(esc键下方的那个键),当在脚本中需要执行一些指令并且将执行的结果赋给变量的时候需要使用“反引号”。</p><p>例如:</p><pre><code class="shell">#!/bin/bashstr=`date +'%Y%m%d'`echo $str20220802</code></pre><h4 id="运算符:"><a href="#运算符:" class="headerlink" title="运算符:"></a>运算符:</h4><ul><li><p>基本语法:</p><ol><li>“$((运算式))”或“$[运算式]”</li><li>expr + - <code>\*</code> / % 分别对应加减乘除和取余,注意这里的乘号是斜杠加*****号,并且这里的运算符之间是需要有空格的。</li></ol></li><li><p>案例:</p><ol><li><p>(2+3)*4: </p><pre><code class="shell">1.result=$[(2+3)*4]2.expr `expr 2 + 3` \* 4</code></pre></li></ol></li></ul><h4 id="条件判断:"><a href="#条件判断:" class="headerlink" title="条件判断:"></a>条件判断:</h4><ul><li><p>基本语法:</p><p><code>[ condition ]</code>,注意condition前后要有空格。条件非空即为true,不非空返回false。</p></li><li><p>常用条件判断:</p><pre><code class="shell">= :字符串比较;-lt:(less than小于);-le:(less equal小于等于);-eq:(equal等于);-gt:(greater than大于);-ge(greater equal大于等于);-ne(not equal不等于)。</code></pre></li><li><p>按照文件权限进行判断:</p><pre><code class="shell">-r,-w,-x:分别代表有读、写、可执行的权限</code></pre></li><li><p>按照文件类型进行判断:</p><pre><code>-f:文件存在,且是一个常规的文件;-e:文件存在exitense;-d:文件存在,且是一个目录directory</code></pre></li><li><p>多条件判断:(&&表示前一条命令执行成功时,才执行后一条命令,||表示上一条命令执行失败后才执行下一条命令)</p></li><li><p>例子:</p><pre><code class="shell">1.判断23是否大于22:[ 23 gt 22 ]2.判断文件是否有写权限:[ -w helloworld.sh ]3.判断/home/self/hello.sh是否存在:[ -e /home/self/hello.sh ]3.[ condition ] && echo OK || echo “not ok”</code></pre></li></ul><h4 id="流程控制:"><a href="#流程控制:" class="headerlink" title="流程控制:"></a>流程控制:</h4><ol><li><h5 id="if判断:"><a href="#if判断:" class="headerlink" title="if判断:"></a>if判断:</h5><pre><code class="shell">if [ command ];then 符合该条件执行的语句elif [ command ];then 符合该条件执行的语句else 符合该条件执行的语句fi</code></pre><p>或者</p><pre><code class="shell">if [ command ]then 符合该条件执行的语句elif [ command ]then 符合该条件执行的语句else 符合该条件执行的语句fi</code></pre></li><li><h4 id="case语句"><a href="#case语句" class="headerlink" title="case语句"></a>case语句</h4><p>基本语法:</p><pre><code class="shell">case 变量 in条件 1) 执行代码块1 ;;条件 2) 执行代码块2 ;;条件 3) 执行代码块3 ;;*) 无匹配后命令序列 esac</code></pre></li><li><h4 id="for循环"><a href="#for循环" class="headerlink" title="for循环"></a>for循环</h4><pre><code class="shell">1.c语言风格for ((i=1; i<=100; i++)) #这里用双括号将循环条件扩起来do echo $idone2.python风格for i in {1..100} #或者这里用之前提到的$*、$@。do echo $idone3.seq使用for i `seq 1 100`do echo $idone</code></pre></li><li><h4 id="while循环"><a href="#while循环" class="headerlink" title="while循环"></a>while循环</h4><pre><code class="shell">whilei [ condition ]do 程序done</code></pre></li></ol><h4 id="read读取控制台输入"><a href="#read读取控制台输入" class="headerlink" title="read读取控制台输入"></a>read读取控制台输入</h4><ul><li><p>语法:read(选项)(参数)</p><pre><code>选项:-p:指定读取值时的提示符-t:指定读取值时等待的时间(秒)参数:变量:指定读取值的变量名</code></pre></li></ul><h4 id="系统函数"><a href="#系统函数" class="headerlink" title="系统函数"></a>系统函数</h4><ul><li><p><code>basename</code>:用法:basename string/pathname suffix ,如果有后缀suffix的话,那么会将string或者pathname中的suffix去除。</p><pre><code class="shell">basename /home/ouyangcan/test.sh -> /home/ouyangcan/test.shbasename /home/ouyangcan/test.sh .sh -> /home/ouyangcan/test</code></pre></li><li><p><code>dirname</code>:用法:dirname 文件绝对路径 (从给定的包含文件名的绝对路径中去除掉文件名,返回剩下的目录部分。)</p><pre><code>dirname /home/ouyangcan/test.sh -> /home/ouyangcan</code></pre></li></ul><h4 id="自定义函数"><a href="#自定义函数" class="headerlink" title="自定义函数"></a>自定义函数</h4><ul><li>语法:</li></ul><pre><code>[function] funname[()]{ Action; [return int];}funname #最后通过funname来调用注:1.其中中括号扩起来的部分都是可写可不写的部分。2.要想调用函数,必须先声明,shell脚本逐行运行,不会预先编译。3.函数返回值只能通过$?系统变量获得,可以显示加return返回,不加的话就以最后一条语句的运行结果作为返回值。return后跟0~255</code></pre><h4 id="shell工具"><a href="#shell工具" class="headerlink" title="shell工具"></a>shell工具</h4><ul><li><strong>cut</strong>:</li></ul><p>在文件中负责剪切数据用,从文件的每一行剪切字节、字符和字段将他们输出。</p><pre><code class="shell">cut [选项参数] filename-f:列号,提取多少列-d:分隔符,按照指定分隔符分割列eg:cut -d " " -f 1,2 cut.txt(-2表示从1到2,2-表示2和2后面的所有列)</code></pre><ul><li><strong>sed</strong>:</li></ul><p>sed是一种流编辑器,一次处理一行内容,处理时把当前处理行存储在临时缓冲区中,成为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送完屏幕,接着处理下一行,不断重复直到文件末尾,而文件内容并没有改变,除非你使用重定向存储输出。</p><pre><code>sed [选项参数] 'command' filename选项参数:-e,直接在指令模式上进行的动作编辑,只有一个命令不需要加-e,多个命令则需要逐次在每个命令钱添加-e。command: a:a的后面可以接字串,在下一行出现。 #sed "2a mei mv" sed.txt,在第二行插入mei nv d:删除 #sed "/wo/d" sed.txt,删除包含wo的行 s:查找并替换#sed "s/wo/ni/g" sed.txt#将文件中的wo全部替换成ni,如果不加/g则只替换第一个wo。g表示global。</code></pre><ul><li><strong>awk</strong>:</li></ul><p>一个强大的文本分析工具,把文件逐行的读入,以空格为<strong>默认</strong>分隔符将每行切片,切开的部分再进行分析处理。</p><pre><code>awk [选项参数] 'pattern1{action1} pattern2{action2} ...' filenamepattern:表示awk在数据中查找的内容,就是匹配模式。选项参数: -F:指定输入文件的分隔符 -v:赋值一个用户定义变量 #-v i=1 $n:n表示数字,如果为0的话表示所有的内容,其他的则为第n列的内容。 eg: awk -F : 'BEGIN{print "user,shell"} {print $1","$7} END{print "ouyangcan,/bin/nbsh"}' passwd内置变量: FILENAME:文件名;NR:已读的记录数;NF:浏览记录的域的个数(切割后列的个数) eg:awk -F : '{print FILENAME "," NR "," NF}' passwd</code></pre><ul><li><strong>sort</strong>:</li></ul><p>将文件进行排序,并将排序结果标准输出。</p><pre><code>sort (选项)(参数)选项: -n:依照数值的大小排序 -r:依照数值的顺序排序 -t:设置排序时使用的分隔字符 -k:指定需要排序的列eg: sort -t : -nrk 2 sort.sh</code></pre><ul><li><p>grep:</p><p> grep (global search regular expression(RE) and print out the</p></li></ul><p>line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。用于过滤/搜索的特定字符。可使用正则表达式能多种命令配合使用,使用上十分灵活。</p><ul><li><p>getopts:</p><p>经常和while和case一起使用,一般用法:</p><pre><code class="shell">while getopts 'h:j:m:u' OPT; do case $OPT in j) S_DIR="$OPTARG";; m) D_DIR="$OPTARG";; u) upload="true";; h) func;; ?) func;; esacdoneecho $S_DIRecho $D_DIRecho $uploadsh test.sh -j /data/usw/web -m /opt/data/web#选项后面跟着的就是OPTARG。##输出结果/data/usw/web/opt/data/webfalse</code></pre></li><li><p>ps:</p><p>Linux中的ps命令是<code>Process Status</code>的缩写。ps命令用来列出系统中当前运行的那些进程。ps 为我们提供了进程的一次性的查看,它所提供的查看结果并不动态连续的;ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信息,就可以使用top命令。</p></li></ul><pre><code>使用方式:ps [options] [--help]说明:显示瞬间行程 (process) 的动态参数:ps的参数非常多, 在此仅列出几个常用的参数并大略介绍含义-A 列出所有的进程-w 显示加宽可以显示较多的资讯-au 显示较详细的资讯-aux 显示所有包含其他使用者的行程</code></pre>]]></content>
</entry>
<entry>
<title>算法面试题</title>
<link href="/2022/07/21/%E7%AE%97%E6%B3%95%E9%9D%A2%E8%AF%95%E9%A2%98/"/>
<url>/2022/07/21/%E7%AE%97%E6%B3%95%E9%9D%A2%E8%AF%95%E9%A2%98/</url>
<content type="html"><![CDATA[<ul><li>给你一个整数数组 nums ,请计算数组的 中心下标 。数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 .</li></ul><h4 id="方法一:前缀和"><a href="#方法一:前缀和" class="headerlink" title="方法一:前缀和"></a>方法一:前缀和</h4><p>思路</p><p>记数组的全部元素之和为 total,当遍历到第 i 个元素时,设其左侧元素之和为 sum,则其右侧元素之和为 total - num[i] - sum.左右侧元素相等即为sum=total−nums[i]-sum,即 2sum+num[i]=total。</p><pre><code>func pivotIndex(nums []int) int { total := 0 for _, v := range nums { total += v } sum := 0 for i, v := range nums { if 2*sum+v == total { return i } sum += v } return -1}</code></pre>]]></content>
<categories>
<category> 面试错题 </category>
</categories>
<tags>
<tag> 面试 </tag>
</tags>
</entry>
<entry>
<title>go面试错题</title>
<link href="/2022/07/21/go%E9%9D%A2%E8%AF%95%E9%94%99%E9%A2%98/"/>
<url>/2022/07/21/go%E9%9D%A2%E8%AF%95%E9%94%99%E9%A2%98/</url>
<content type="html"><![CDATA[<ul><li><h4 id="Golang可以复用C-x2F-C-的模块,这个功能叫Cgo-这一说法是否正确。"><a href="#Golang可以复用C-x2F-C-的模块,这个功能叫Cgo-这一说法是否正确。" class="headerlink" title="Golang可以复用C/C++的模块,这个功能叫Cgo,这一说法是否正确。"></a><strong>Golang可以复用C/C++的模块,这个功能叫Cgo,这一说法是否正确。</strong></h4></li></ul><p>不正确,Cgo不支持C++,但是可以通过C来封装C++的方法实现Cgo调用。</p><ul><li><h4 id="对于以下代码,描述正确的是"><a href="#对于以下代码,描述正确的是" class="headerlink" title="对于以下代码,描述正确的是:"></a><strong>对于以下代码,描述正确的是:</strong></h4></li></ul><pre><code>package mainimport ( "fmt" "sync")func main() { var wg sync.WaitGroup intSlice := []int{1, 2, 3, 4, 5} wg.Add(len(intSlice)) ans1, ans2 := 0, 0 for _, v := range intSlice { vv := v go func() { defer wg.Done() ans1 += v ans2 += vv }() } wg.Wait() fmt.Printf("ans1:%v,ans2:%v", ans1, ans2) return}</code></pre><pre><code>ans1不一定是 15, ans2 不一定是 15.</code></pre><p>闭包只是绑定的v这个变量,当goruntine执行时可能for循环已经执行,v的值已经变化。</p><p>个人理解可能当其中一个v赋值为1时,另外一个goruntine中的v也是1,不一定满足1+2+3+4+5。</p><ul><li><h4 id="关于slice或map操作,下面正确的是()"><a href="#关于slice或map操作,下面正确的是()" class="headerlink" title="关于slice或map操作,下面正确的是()"></a>关于slice或map操作,下面正确的是()</h4></li></ul><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207211831356.png" > </sapn> </p><pre><code>A,C,D</code></pre><p>make只用来创建slice,map,channel。 其中map使用前必须初始化。 append可直接动态扩容slice,也就是说空切片可以直接append,而map不行。</p><ul><li><h4 id="关于go-vendor,下面说法正确的是("><a href="#关于go-vendor,下面说法正确的是(" class="headerlink" title="关于go vendor,下面说法正确的是("></a>关于go vendor,下面说法正确的是(</h4></li></ul><pre><code>A。基本思路是将引用的外部包的源代码放在当前工程的vendor目录下面B。编译go代码会优先从vendor目录先寻找依赖包C。可以指定引用某个特定版本的外部包D。有了vendor目录后,打包当前的工程代码到其他机器的$GOPATH/src下都可以通过编译</code></pre><pre><code>A,B,D</code></pre><p>go vendor无法精确的引用外部包进行版本控制,不能指定引用某个特定版本的外部包;只是在开发时,将其拷贝过来,但是一旦外部包升级,vendor下的代码不会跟着升级,而且vendor下面并没有元文件记录引用包的版本信息,推荐go mod ,go mod 已经完美支持各模块的版本控制。</p><ul><li><h4 id="new和make有什么区别?"><a href="#new和make有什么区别?" class="headerlink" title="new和make有什么区别?"></a>new和make有什么区别?</h4></li></ul><p>在 Go 语言中,内置函数 <code>make</code> 仅支持 <code>slice</code>、<code>map</code>、<code>channel</code> 三种数据类型的内存创建,<strong>其返回值是所创建类型的本身,而不是新的指针引用</strong>。make的优势本质上在于 <code>make</code> 函数在初始化时,会初始化 <code>slice</code>、<code>chan</code>、<code>map</code> 类型的内部数据结构,<code>new</code> 函数并不会。例如:在 <code>map</code> 类型中,合理的长度(len)和容量(cap)可以提高效率和减少开销。</p><ul><li><h4 id="GMP模型能说一下嘛"><a href="#GMP模型能说一下嘛" class="headerlink" title="GMP模型能说一下嘛"></a>GMP模型能说一下嘛</h4></li></ul><p><a href="https://blog.csdn.net/S_FMX/article/details/115771606?ops_request_misc=&request_id=&biz_id=102&utm_term=GMP%E6%A8%A1%E5%9E%8B&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3-115771606.142%5Ev35%5Eexperiment_28w_v1&spm=1018.2226.3001.4187">链接</a></p><ul><li><h4 id="进程,协程,线程的概念"><a href="#进程,协程,线程的概念" class="headerlink" title="进程,协程,线程的概念"></a>进程,协程,线程的概念</h4><p>1、进程</p><pre><code> 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。</code></pre><p> 2、线程</p><pre><code> 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,而拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程也由操作系统调度(标准线程是这样的)。只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。</code></pre><p> 3、协程</p><pre><code> 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。 一个应用程序一般对应一个进程,一个进程一般有一个主线程,还有若干个辅助线程,线程之间是平行运行的,在线程里面可以开启协程,让程序在特定的时间内运行。进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。(全局变量保存在堆中,局部变量及函数保存在栈中)线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是这样的)。协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。一个应用程序一般对应一个进程,一个进程一般有一个主线程,还有若干个辅助线程,线程之间是平行运行的,在线程里面可以开启协程,让程序在特定的时间内运行。</code></pre><ul><li><h4 id="说一说select"><a href="#说一说select" class="headerlink" title="说一说select"></a>说一说select</h4>Go中的select可以理解为一个多路复用模型,当检测到有IO变化的时候,就会执行对应的case下的语句,类似于switch,不过select语句是用来监听和channel有关的IO操作,用于实现main主线程和goruntine之间的互动,在使用的时候如果不设置default默认条件的话,当没有IO操作发生的时候select语句就会一直阻塞,如果有一个或多个IO操作发生时,Go运行时会随机选择一个case执行,但此时将无法保证执行顺序;对于case语句,如果存在信道值为nil的读写操作,则该分支将被忽略,可以理解为相当于从select语句中删除了这个case;对于空的 select语句,会引起死锁;对于在 for中的select语句,不能添加 default,否则会引起cpu占用过高的问题。</li></ul></li><li><h4 id="Golang-channel了解吗,channel的工作原理是什么?"><a href="#Golang-channel了解吗,channel的工作原理是什么?" class="headerlink" title="Golang channel了解吗,channel的工作原理是什么?"></a>Golang channel了解吗,channel的工作原理是什么?</h4><p><a href="https://louyuting.blog.csdn.net/article/details/85231944?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1-85231944-blog-122325256.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1-85231944-blog-122325256.pc_relevant_aa&utm_relevant_index=1">链接</a></p><p>Go不推荐用共享内存方式来通信,推荐使用通信的方式来共享内存。channel用于多个goroutine之间传递数据,且保证整个过程的并发安全性。管道分为无缓存的管道和有缓存的管道。无缓存管道的发送和接收是同步的,任意一个操作都无法离开另一个操作单独存在。否则就会发生deadlock死锁。有缓存管道的发送和接受可以不同步的,当通道中没有要接收的值时,接收动作会阻塞;当通道缓冲区满时发送操作会阻塞。底层的数据模型如下: <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207291505806.png" > </sapn> </p></li></ul><p>对一个已经被 <code>close</code> 过的 <code>channel</code> 进行<strong>接收</strong>操作依然可以接受到之前已经成功发送的数据;如果 <code>channel</code> 中已经没有数据的话将产生一个零值的数据。被关闭的通道不会被置为 <code>nil</code> 。如果尝试对已经关闭的通道进行发送,将会触发 <code>panic</code>。另外,如果我们试图关闭一个已经关闭了的通道,也会引发 <code>panic</code>。由于通道类型是引用类型,所以它的零值就是 <code>nil</code> 。换句话说,当我们只声明该类型的变量但没有用 <code>make</code> 函数对它进行初始化时,该变量的值就会是 <code>nil</code>。</p><ul><li><h4 id="谈一下map"><a href="#谈一下map" class="headerlink" title="谈一下map"></a>谈一下map</h4><p>链接<a href="https://blog.csdn.net/qq_48826531/article/details/125907606?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165908031016782395396581%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165908031016782395396581&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-125907606-null-null.142%5Ev35%5Eexperiment_28w_v1&utm_term=go%20map%E5%BA%95%E5%B1%82&spm=1018.2226.3001.4187">map</a></p><p>map是一个key—value键值对结构,作为无序键值对集合,map要求key必须是支持相等运算符(==,!=)的数据类型,如:数字、字符串、指针、数组、结构体以及对应的接口;对于切片、函数、通道类型这类具有引用语义的不能作为map的key值。map底层采用hash表结构,通过键值对进行映射。 键通过<a href="https://so.csdn.net/so/search?q=%E5%93%88%E5%B8%8C&spm=1001.2101.3001.7020">哈希</a>函数生成哈希值,然后go底层的map数据结构就存储相应的hash值,进行索引,最终是在底层使用的数组存储key,和value。</p><ul><li><h4 id="GC(标记清理-gt-三色标记法-gt-混合写屏障)"><a href="#GC(标记清理-gt-三色标记法-gt-混合写屏障)" class="headerlink" title="GC(标记清理 -> 三色标记法 -> 混合写屏障)"></a>GC(标记清理 -> 三色标记法 -> 混合写屏障)</h4><p>堆<a href="https://so.csdn.net/so/search?q=%E5%86%85%E5%AD%98&spm=1001.2101.3001.7020">内存</a>上分配的数据对象,不会再使用时,不会自动释放内存,就变成垃圾,在程序的运行过程中,如果不能及时清理,会导致越来越多的内存空间被浪费,导致系统性能下降。</p><p>因此需要内存回收,内存回收分为两种方式</p><p>1.手动释放占用的内存空间</p><p>可能会出现的问题:<br>悬挂指针: 释放的早了,后续对数据的访问就会出错,因为对应的内存空间可能已经清空,重新分配,甚至是归还给操作系统了。<br>内存泄漏: 如果忘了释放,一直占用内存,导致内存泄漏。</p><p>2.自动内存回收</p><p>开发人员无需手动管理释放已经分配但是没有引用的对象内存,而由程序自动检测对象决定是否要回收其内存。</p><p>系统如何检测哪些应该是被回收的数据对象呢?<br><strong>核心思想:</strong>程序中用得到的数据,一定是可以从栈或数据段这些根节点追踪得到的数据,追踪不到的数据,肯定用不到,也就是垃圾。</p></li></ul><h5 id="标记清除法"><a href="#标记清除法" class="headerlink" title="标记清除法"></a>标记清除法</h5><p> 把根数据段上的数据作为root,基于他们进行进一步的追踪,追踪到的数据就进行标记,最后把没有标记的对象当作垃圾进行释放。</p><p> 开启STW,<br> 从根节点出发,标记所有可达对象<br> 停止STW,然后回收所有未标记的对象。</p><h5 id="三色标记法"><a href="#三色标记法" class="headerlink" title="三色标记法"></a>三色标记法</h5><p> 白灰黑</p><p> 初始时,所有对象都为白色,<br> GC开始,开启SWT,遍历堆栈root,将直接可达的对象标记为灰色,<br> 遍历灰色结点,将直接可达的对象标记为灰色,自身标记为黑色,<br> 继续执行第三步同样的步骤,直到所有能够访问到的结点都被标记为黑色,<br> 关闭SWT,回收所有白色标记的对象。<br> 如果没有SWT,程序正常执行,可能会有如下的情况,导致对象被误当作垃圾回收。<br> 白色对象本来被一个灰色对象引用,但是该灰色对象将该引用赋给了黑色对象,灰对白的引用断开。此时,由于不会对黑色对象的引用进行检测标记,即该白色节点即使被引用也无法被标记为灰色,最终当作垃圾处理掉。</p><p> 三色标记法出现对象丢失,要满足以下两个条件:</p><ul><li>条件一:<strong>白色对象被黑色对象引用</strong></li><li>条件二:<strong>灰色对象与白色对象之间的可达关系遭到破坏</strong></li></ul><p> 只要破坏两个中的任何一个不会导致对象丢失的发生。</p><p> 两种不变式,如何破坏两个条件</p><p> <strong>强不变式:</strong> 不允许黑色对象引用白色对象<br> <strong>弱不变式:</strong> 黑色对象可以引用白色对象,但是白色对象必须直接或间接被灰色对象引用。(保证白色对象一定会被扫描到)<br> go对上述规则的两种实现机制:</p><h5 id="插入写屏障"><a href="#插入写屏障" class="headerlink" title="插入写屏障"></a>插入写屏障</h5><p> 当一个对象引用另外一个对象时,将另外一个对象标记为灰色。</p><p> 插入屏障仅会在堆内存中生效,不对栈内存空间生效,这是因为go在并发运行时,大部分的操作都发生在栈上,函数调用会非常频繁。数十万goroutine的栈都进行屏障保护自然会有性能问题。</p><p> 如果一个栈对象 黑色引用白色对象,白色对象依然会被当作垃圾回收。<br> 因此,最后还需要对栈内存 进行STW,重新rescan,确保所有引用的被引用的栈对象都不会被回收。</p><h5 id="删除写屏障"><a href="#删除写屏障" class="headerlink" title="删除写屏障"></a>删除写屏障</h5><p> 当一个白色对象被另外一个对象时解除引用时,将该被引用对象标记为灰色(白色对象被保护)</p><p> 缺点:产生内存冗余,如果上述该白色对象没有被别的对象引用,相当于还是垃圾,但是这一轮垃圾回收并没有处理掉他。</p><h5 id="混合写屏障法"><a href="#混合写屏障法" class="headerlink" title="混合写屏障法"></a>混合写屏障法</h5><p> GC刚开始的时候,会将栈上的可达对象全部标记为黑色。</p><p> GC期间,任何在栈上新创建的对象,均为黑色。<br> 将栈上的可达对象全部标黑,最后无需对栈进行STW,就可以保证栈上的对象不会丢失</p><p> 堆上被删除的对象标记为灰色</p><p> 堆上新添加的对象标记为灰色</p><p> 总结<br> go 1.3 之前采用标记清除法,需要STW<br> go 1.5 采用三色标记法,插入写屏障机制(只在堆内存中生效),最后仍需对栈内存进行STW<br> go 1.8 采用混合写屏障机制,屏障限制只在堆内存中生效。避免了最后节点对栈进行STW的问题,提升了GC效率</p></li></ul>]]></content>
<categories>
<category> 面试错题 </category>
</categories>
<tags>
<tag> 面试 </tag>
</tags>
</entry>
<entry>
<title>hexo搭建博客遇到的问题</title>
<link href="/2022/07/09/hexo%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/"/>
<url>/2022/07/09/hexo%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<h4 id="使用MarkDown的相关问题"><a href="#使用MarkDown的相关问题" class="headerlink" title="使用MarkDown的相关问题"></a>使用MarkDown的相关问题</h4><p>在写文章的时候,我们可以插入图片和相关资源使得文章更加丰富生动,但是在本地写<code>MarkDown</code>文件时,上传的本地图片是无法实现在网络上或是在另外一台设备上访问的。我在完成基于github使用hexo博客的搭建后,我发现了一些问题,关于 gitalk评论模块的一些坑我已经写在<a href="https://magictmac1.github.io/2022/07/07/Hexo%20_Themes/">themes</a>那片博客里了,剩下的一些写在这里。</p><h4 id="文章内容显示不全"><a href="#文章内容显示不全" class="headerlink" title="文章内容显示不全"></a>文章内容显示不全</h4><p> 我在生产部署之后进行 <code>hexo s</code> 本地测试的时候发现我的使用了图片的文章都显示不全,而且很统一的在文章第一个出现图片的地方之后就不显示接下来的内容了,而没有图片的hexo初始化就自带的 <code>hello world </code> 就没有出现这样的情况,因为已经修复了就不放bug图了,直接说解决方法吧。</p><h4 id="办法一:同名目录-相对路径"><a href="#办法一:同名目录-相对路径" class="headerlink" title="办法一:同名目录 + 相对路径"></a>办法一:同名目录 + 相对路径</h4><p>在使用<code>Hexo</code>写博客时,每一篇文章创建一个同名目录,并在这个同名目录中放置需要插入的图片文件,在<code>MarkDown</code>文章中插入使用图片的相对路径,然后在部署博客的时候也一同将这个文件夹上传到服务器。</p><ol><li><p>修改配置文件<code>_config.yml</code>使得每一次新建文章的时候自动生成同名目录。(方法二中其实就不需要这个选项了,使用方法二可以改为false)</p><pre><code>post_asset_folder: true</code></pre><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102347474.png" > </sapn> </p></li></ol><p>2.修改MarkDown编辑器配置,实现粘贴图片时自动将图片文件复制一份到所对应的同名目录。</p><p>我使用的Typora编辑MarkDown文件,通过<code>ctrl + ,</code> 打开Typora的设置,并按图片中完成相关设置。</p><pre><code>./${filename}</code></pre><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102351926.png" > </sapn> </p><p>完成这样的设置后,每当我们在<code>Typora</code>中粘贴图片的时候就会将图片复制到同名目录下。</p><p>但是需要注意的是,这样上传到<code>Hexo</code>依旧不能解决图片无法访问的问题,因为图片的路径还是本地的路径,只是这个图片所属的本地的文件夹是和文章同名的。 <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102351025.png" > </sapn> </p><p>解决办法:将绝对路径变成相对路径,这样在<code>Hexo</code>服务器上就会自动的在与文章同名的那个文件夹里面找图片文件,所以只需要删去前面的一部分,只留下图片的文件名。</p><p>这样做可以实现在博客上能展现图片了,但是有一个弊端就是本地是看不见图片的了。本地效果如下: <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102352359.png" > </sapn> </p><p>总结这个方法:</p><p>本地看不到图片的效果,但是上传至Hexo后是可以查看的,能解决Hexo上查看本地图片的问题。<br>但是仍然不能解决Hexo以外的诸多博客平台的本地图片访问问题,对于CSDN、简书来说它都有自己的图床,所以可以上传到对应平台的图床,然后用网络的链接访问图片。<br>使得Hexo文件变得臃肿,随着博客文章的积累,用到的图片会在每次部署和上传到服务器时一并被携带上传,造成部署和上传的压力,使得上传的速度变得很慢。<br>由于博客部署在GitHub Pages,就会导致加载博客文章时,一大部分时间用于请求Github Pages服务器加载图片文件,再加上Github Pages服务器在大陆访问有时很慢的情况,使得博客网页加载奇慢无比。<br>综上,这个办法并不是长久有效的。</p><h4 id="方法二:Github-PicGo"><a href="#方法二:Github-PicGo" class="headerlink" title="方法二:Github + PicGo"></a>方法二:Github + PicGo</h4><p>因为上一个方法每一次都需要重新将之前的图片资源重复部署,导致速度越来越慢,不是一个一劳永逸的方法,所以我找到了更好的方法,那就是使用<strong>图床</strong>。</p><p>图床网上也有很多免费的,但是大部分都不靠谱,如果放在免费的图床上我们需要米娜对一一些问题:</p><ol><li>网络图床有可能突然就不维护了,那么我们放的图片也就不翼而飞了,而如果你的图片又没有备份的话,那么所有用到这些图片的文件都会被涉及到,这些图片也就访问不了,消失在网络的大海里。</li><li>免费的图床有额度限制,一般可用的空间不会太大。</li><li>本地写文章时不够简便,需要每张图片手动上传。</li></ol><p>但是我扣,所以我选择全球最大的同性交友网站Github作为免费床图😁,接下来讲一下操作流程。</p><h4 id="Github设置"><a href="#Github设置" class="headerlink" title="Github设置"></a>Github设置</h4><ul><li>首先创建一个专门用来保存博客上传图片的仓库,基本操作就不演示了。</li><li>然后我们生成GitHub Tokens,点击<code>Settings</code>,进入Settings后,点击左侧下方的<code>Developer settings</code>,网页跳转后,选左边的<code>Personal access tokens</code>,点击<code>Generate a personal access token</code>,<code>Note</code>这里填写为什么创建这个Token,可随意填写,下方勾上<code>repo</code>即可。然后滑到最下方点击<code>Generate token</code>。然后会生成一条Token信息,生成的Token只会出现一次,记得复制保存。(省略了一些简单的步骤的截图,大家应该都懂)</li></ul><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102319201.png" > </sapn> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102321616.png" > </sapn> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102326868.jpg" > </sapn> </p><h4 id="Typora设置"><a href="#Typora设置" class="headerlink" title="Typora设置"></a>Typora设置</h4><ul><li><p>打开Typora,点击左上角菜单栏的<code>Typora</code>,点击弹出框里下方的<code>偏好设置</code>,(macOS是这样,Win的自行搜索)设置成如下。</p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102329445.png" > </sapn> </p></li></ul><h4 id="PicGo设置"><a href="#PicGo设置" class="headerlink" title="PicGo设置"></a>PicGo设置</h4><p> 打开运行PicGo,左侧打开打开详细窗口,选择图床设置(Github图床)。<br> 参数设置说明:</p><p> 仓库名:表示远程仓库地址,固定格式 Github用户名/仓库名,前期准备用到的仓库<br> 分支名:表示分支,默认填入master,需要根据自己Github上的分支进行填写,看个人设置<br> Token:填入Github中生成的Token,就是让复制保存的那个<br> 存储路径:可以自定义一个文件路径<br> 自定义域名:建议使用https:cdn.jsdelivr.net/gh/Github用户名/仓库名<br> 最后记得设为默认图床,然后在正式使用的时候会进行i个测试,会告诉你测试结果是否成功。(macOS和Win不一样,WIn好像设置里有测试的选项,macOS没有)我是测试完了之后再写的,所以没有截图。<br> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102332415.png" > </sapn> </p><p>完成上述的步骤就完成所以的配置了,可以<code>hexo new test</code>新建一个文件上传图片测试一下了,</p><h4 id="Tips:快捷键及相关配置"><a href="#Tips:快捷键及相关配置" class="headerlink" title="Tips:快捷键及相关配置"></a>Tips:快捷键及相关配置</h4><p>支持快捷键command+shift+p(macOS)或者control+shift+p(windows\linux)用以支持快捷上传剪贴板里的图片(第一张)。</p><p>PicGo支持自定义快捷键,使用方法见配置手册。</p><p>注:可以将快捷键设置为ctrl+shift+c</p><p>总结<br>将上面的步骤都设置好,每次截图之后,都可以按一下ctrl+shift+c,这样就会将剪切板上面的截图转化为在线网络图片链接,简直就是爽的不要不要的,关键是背靠 GitHub ,比自建服务器都稳!</p>]]></content>
<categories>
<category> 博客搭建 </category>
</categories>
<tags>
<tag> blog </tag>
</tags>
</entry>
<entry>
<title>Hexo_Themes</title>
<link href="/2022/07/07/Hexo%20_Themes/"/>
<url>/2022/07/07/Hexo%20_Themes/</url>
<content type="html"><![CDATA[<h3 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h3><p>在 Hexo 中有两份主要的配置文件,其名称都是 <code>_config.yml</code>。 其中,一份位于站点根目录下,主要包含 Hexo 本身的配置;另一份位于主题目录下,这份配置由主题作者提供,主要用于配置主题相关的选项。</p><p>为了描述方便,在以下说明中,将前者称为 <strong>站点配置文件</strong>, 后者称为 <strong>主题配置文件</strong>。这个是模版的<a href="https://fushaolei.github.io/hexo-theme-white/archives/">demo</a>和<a href="https://github.com/FuShaoLei/hexo-theme-white">github仓库</a></p><h3 id="white主题配置(目前只学会用一个)"><a href="#white主题配置(目前只学会用一个)" class="headerlink" title="white主题配置(目前只学会用一个)"></a><a href="https://github.com/MagicTmac1/hexo-theme-white">white</a>主题配置(目前只学会用一个)</h3><p>进入站点目录下的themes目录,将主题包下载到本地,然后修改站点配置文件_config.yml中的theme为下载下来的主题包的名字(<strong>这两个一定要相同!</strong>)</p><h2 id=""><a href="#" class="headerlink" title=""></a> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102353818.png" > </sapn> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102355498.png" > </sapn> </h2><h2 id="主题配置"><a href="#主题配置" class="headerlink" title="主题配置"></a>主题配置</h2><blockquote><p>其实config文件里写的很明白了,现在就重新列一下,添加一些不必要的说明</p></blockquote><h3 id="可自定义style"><a href="#可自定义style" class="headerlink" title="可自定义style"></a>可自定义style</h3><pre><code class="yml">############## style ##############style: layout: max-width: 1130px #总体宽度 post-max-width: 800px #文章内容宽度 color: theme-main: "#1A98FF" # 主色调 theme-secondary: "#DDF0FF" # 次色调 text-main: "#333333" # 文字主色调 text-secondary: "#898FA0" # 文字次色调 animation: open: true # 如果开启动画的话会引入animation.css</code></pre><h3 id="主页配置"><a href="#主页配置" class="headerlink" title="主页配置"></a>主页配置</h3><h4 id="home页和archive可选配置"><a href="#home页和archive可选配置" class="headerlink" title="home页和archive可选配置"></a>home页和archive可选配置</h4><pre><code class="yml"># home页可选类型home: type: "img" # 主页的类型,可选 home | img | simple# archive页可选类型archive: type: "simple" # archive的类型,可选 img | simple</code></pre><p>type为home就是一个封面,为img就是图片加标题的形式,simple就是极简模式</p><h3 id="随机cover"><a href="#随机cover" class="headerlink" title="随机cover"></a>随机cover</h3><p>当你懒的找封面而又想用img模式的时候,我为你准备了些随机封面</p><pre><code class="yml">archive_img_mode: default_cover: #默认的cover - https://cdn.jsdelivr.net/gh/fushaolei/[email protected]/cover/01.jpg - https://cdn.jsdelivr.net/gh/fushaolei/[email protected]/cover/02.jpg - https://cdn.jsdelivr.net/gh/fushaolei/[email protected]/cover/03.jpg - https://cdn.jsdelivr.net/gh/fushaolei/[email protected]/cover/04.jpg - https://cdn.jsdelivr.net/gh/fushaolei/[email protected]/cover/05.jpg - https://cdn.jsdelivr.net/gh/fushaolei/[email protected]/cover/06.jpg</code></pre><blockquote><p>图片均来自于bing的每日图片,版权归图片原作者所有,我只是搬到了自己的仓库方便使用,如果有侵犯到你的权益,请和我联系 ( •̀ ω •́ )</p></blockquote><h3 id="浏览器标签页配置"><a href="#浏览器标签页配置" class="headerlink" title="浏览器标签页配置"></a>浏览器标签页配置</h3><pre><code class="yml"># iconicon: #标签页图标,这里可填链接(可以直接将图片地址拿过来,我拿的百度小黄鸭的)# headersite_name: white(对应下面的这个浏览器标签)</code></pre><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102356109.png" > </sapn> </p><h3 id="menu"><a href="#menu" class="headerlink" title="menu"></a>menu</h3><pre><code class="yml">menu: HOME: / BLOG: /archives</code></pre><h3 id="全局搜索"><a href="#全局搜索" class="headerlink" title="全局搜索"></a>全局搜索</h3><pre><code class="yml">## 本地搜索search: open: false # 是否开启 page: /search # 页面路径(通常命名为search)</code></pre><p>如果你想使用的话,请先到根目录执行</p><pre><code class="npm">npm install hexo-generator-search --save</code></pre><p>然后新建一个名为search的page</p><pre><code class="npm">hexo new page "search"</code></pre><p>进入这个文件夹,更改它的<code>index.md</code>文件,示例如下</p><pre><code class="md">---layout: searchcover: #你还可以自定义cover---</code></pre><p>然后将open设置为true即可开启</p><h3 id="自我介绍"><a href="#自我介绍" class="headerlink" title="自我介绍"></a>自我介绍</h3><blockquote><p>当你的home页有用到type home模式的话 请配置此项</p></blockquote><pre><code class="yml"># 自我介绍intro: title: Hi.I'm White. sub: 'A [White](https://github.com/FuShaoLei/hexo-theme-white) theme for [Hexo](http://hexo.io/)' # markdown语法 avator: https://cdn.jsdelivr.net/gh/fushaolei/img/20200524104925.jpg #头像 暂时还没用到 author: white #所有文章的默认作者</code></pre><h3 id="联系方式"><a href="#联系方式" class="headerlink" title="联系方式"></a>联系方式</h3><pre><code class="yml">#联系方式 #更多图标:https://remixicon.com/contact: Github: - https://github.com/MagicTmac1/hexo-theme-white - ri-github-line Email: - mailto:[email protected] - ri-mail-line</code></pre><p>格式就是</p><pre><code class="yml">名字: - 链接 - 图标 </code></pre><h3 id="文章toc设置"><a href="#文章toc设置" class="headerlink" title="文章toc设置"></a>文章toc设置</h3><pre><code class="yml"># 文章toc索引栏设置toc: open: true # 是否开启 side: true # 选择toc的位置,填true的话toc将会显示在文章的侧边,填false的话 toc将出现在文章的开头 max: 2 #最大深度 min: 2 #最小深度</code></pre><p>其中side如果设置为false的话,将会出现在文章的top部分,如果设置为true的话,将会出现在侧边 min设置的是最小深度,max设置的是最大深度,<del>如上面配置所示,min为2,说明h2索引是至少要出现的,不会出现h1索引 ( 突然不知道怎么表达,</del> 如果不理解的话建议你试试 😂</p><h3 id="highlight"><a href="#highlight" class="headerlink" title="highlight"></a>highlight</h3><p>代码高亮,想要使用代码高亮,得先把根目录的**<code>_config.yml</code>里的highlight的enable置成false**</p><pre><code class="yml"># 插件plugins: highlightjs: js: https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js css: https://cdn.jsdelivr.net/npm/[email protected]/styles/github.css # more: https://www.jsdelivr.com/package/npm/highlight.js?path=styles</code></pre><h3 id="评论系统"><a href="#评论系统" class="headerlink" title="评论系统"></a>评论系统</h3><pre><code class="yml"># 评论系统设置comments: open: false #是否开启评论系统 system: gitalk #选择评论系统 可选 valine gitalk livere # Valine valine: appid: #Leancloud应用的AppID 这里和下面的要换成你自己的啊QAQ appkey: #Leancloud应用的AppKey verify: false #验证码 notify: true #评论回复提醒 avatar: robohash #评论列表头像样式:''/mm/identicon/monsterid/wavatar/retro/hide #头像类型可见: https://valine.js.org/avatar.html placeholder: 留下你来过的痕迹~ #评论框占位符 # Gitalk gitalk: owner: #Github 用户名, repo: #储存评论issue的github仓库名 admin: #Github 用户名 clientID: #`Github Application clientID` clientSecret: #`Github Application clientSecret` #livere livere: # 前往 http://livere.com/ 申请账号 dataId: city #免费版本city dataUid: #安装代码中 data-uid 后面数据</code></pre><h3 id="Gitalk配置教程"><a href="#Gitalk配置教程" class="headerlink" title="Gitalk配置教程"></a>Gitalk配置教程</h3><p>先配置一下 Git <a href="https://github.com/settings/developers">https://github.com/settings/developers</a> 然后选择 OAuth Apps 点击 New OAuth App, <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102356423.png" > </sapn> </p><p>这里注意HomePage URL和callback URL一定要一样!</p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102357218.png" > </sapn> </p><p>做完这些基本就ok了,然后点进去绑定初始化一下,就完成啦! <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102357442.png" > </sapn> </p><blockquote><p><strong>这里写一下遇到的一些问题吧</strong></p><p>gitalk的坑,一个是repo这里 写的应该是<strong>仓库名</strong>,而不是仓库链接或者其他的东西,然后gitalk要上线部署一次才可以,md文件名字最好用英文来命名,如果用中文的话,超出50个字符将会初始化失败,<a href="https://blog.csdn.net/Keith_Prime/article/details/111604291">Gitalk Error: Validation Failed</a>。</p><p>在讲gitalk进行初始化的时候,repo其实不需要重新创建一个仓库(我一开始创建了一个仓库,写的那个仓库的名称,一直出现那个<code>NetWork Error</code>的报错,后来我改成我用来当站点的那个仓库的名称就ok了🤔)</p><p>当我试着把原来的中文名称改为英文时,出现了404的错误,要记得把下图所示的两个地方改为相同的,不然就会出错。将md文件名重新换一个名字,md文档里面的<code>title</code>也要更换。再进行<code>hexo cl</code>、<code>hexo g</code> 、<code>hexo d</code>。</p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207102357946.png" > </sapn> </p></blockquote><h3 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h3><pre><code class="yml"># 页脚footer: Power by [Hexo](http://hexo.io/) Theme by [White](https://github.com/FuShaoLei/hexo-theme-white) # markdown语法#有分类时是否开启menu分类页和自定义名字menu_categories: open: true name: 分类#可自定义归档标签页名字 archive_tab_name: Blog#图片懒加载lazyload: open: true #是否开启</code></pre><p>这里就不bb了 大家应该看的懂</p><h2 id="进阶使用"><a href="#进阶使用" class="headerlink" title="进阶使用"></a>进阶使用</h2><h3 id="平滑升级"><a href="#平滑升级" class="headerlink" title="平滑升级"></a>平滑升级</h3><h4 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h4><p>因为主题的更新比较频繁,所以如果你想舒服用到最新的版本的话,就请使用平滑升级</p><ol><li>在你<strong>根目录</strong>下的<code>source</code>文件夹下新建一个名为<code>_data</code>的<strong>文件夹</strong></li><li>复制<strong>主题文件夹</strong>下的<code>_config.yml</code>到<code>_data</code>文件夹下,重命名为<code>white.yml</code></li></ol><p>好了,到这里差不多完成了,以后你需要改动什么,只需要在这个<code>white.yml</code>中进行修改(在编译时,会自动将此替换<code>_config.yml</code>)w</p><h4 id="升级"><a href="#升级" class="headerlink" title="升级"></a>升级</h4><p>当你看到我的主题有<a href="https://github.com/FuShaoLei/hexo-theme-white/issues/3">变更</a>时,在主题文件中执行<code>git pull</code>拉取最新代码 然后,对比最新主题文件夹下的<code>_config.yml</code> 看看有无新增什么东西,添加到你的<code>white.yml</code>中即可</p><hr>]]></content>
<categories>
<category> 博客搭建 </category>
</categories>
<tags>
<tag> blog </tag>
</tags>
</entry>
<entry>
<title>Github+Hexo blog build</title>
<link href="/2022/07/07/Github+Hexo%20blog%20build%20/"/>
<url>/2022/07/07/Github+Hexo%20blog%20build%20/</url>
<content type="html"><![CDATA[<p>前期准备</p><pre><code>1. Github账号,并创建一个置顶名字的远程仓库。2. Homebrew套件管理器3. Node,Git,Hexo4. NexT主题配置</code></pre><h2 id="1-Github上创建远程仓库"><a href="#1-Github上创建远程仓库" class="headerlink" title="1.Github上创建远程仓库"></a>1.Github上创建远程仓库</h2><p>首先要在Github上创建一个新的指定命名的远程仓库(当然没有账号要先注册啦)</p><p>按照如图所示的方式创建Repository。 <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207110002698.png" > </sapn> </p><p><strong>使用Git Pages配置远程仓库</strong><br>在不购买服务器的前提下,我们的网站需要挂在<a href="https://pages.github.com/">GitHub Pages</a>上。GitHub Pages是面向用户、组织和项目开放的公共静态页面搭建托管服务,可用于搭建个人博客。</p><p>进入GitHub Pages里面有帮助文档,一步步做,完成后就能在浏览器打开<a href="http://username.github.io了./">http://username.github.io了。</a></p><p>我这里使用ssh,因为后续不需要再次使用密码进行部署。</p><pre><code>1.cd ~/.ssh2.ssh-keygen -t rsa -C "[email protected]"</code></pre><p>然后一直回车,最终会生成一个文件在用户目录下,打开用户目录,找到.ssh\id_rsa.pub文件,打开并复制里面的内容,打开你的github主页,进入个人设置 -> SSH 公钥 :将刚复制的内容粘贴到那里,title随便填,保存。</p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207110003640.png" > </sapn> </p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207110003360.png" > </sapn> </p><h2 id="2-HomeBrew-Git-hexo-npm套件安装"><a href="#2-HomeBrew-Git-hexo-npm套件安装" class="headerlink" title="2.HomeBrew ,Git,hexo,npm套件安装"></a>2.HomeBrew ,Git,hexo,npm套件安装</h2><pre><code>1.自行安装homebrew,然后可通过brew安装git和node.jsbrew install gitbrew install node</code></pre><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207110004866.png" > </sapn> </p><pre><code>2.npm install -g hexo-cli </code></pre><p>安装Hexo<br>安装完Node.js 及 Git 后,即可使用npm来安装Hexo:</p><pre><code>$ npm install -g hexo-cli </code></pre><p>初始化Hexo<br>创建一个目录用来作为你的blog目录,例如 blog;并在该目录中进行Hexo的初始化:</p><pre><code>$ hexo init blog(可能会卡顿,卡顿的话就先创建blog文件夹,进入blog进行hexo init)$ cd ~/blog/$ npm install</code></pre><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207110004469.png" > </sapn> </p><p>新建完成后,得到以下目录:</p><pre><code>·|-- _config.yml|-- package.json|-- scaffolds|-- source| |-- _drafts| |-- _posts|-- themes</code></pre><p>至此,你就完成了Hexo的安装及初始化,接下来我们就可以进行本地的预览啦:<br>先安装hexo server</p><pre><code>$ npm install hexo-server</code></pre><p>然后生成静态页面并打开hexo本地服务</p><pre><code>$ hexo generate (或 hexo g)$ hexo server</code></pre><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207110005787.png" > </sapn> </p><p>按命令行提示,打开 <a href="http://localhost:4000/">http://localhost:4000</a> 即可看到默认主题的默认页面了。<br>可能加载会很慢,因为默认主题中使用了些Google的资源,后面更换主题就会快很多了。</p><p> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207110006186.png" > </sapn> </p><h2 id="3-配置远程仓库"><a href="#3-配置远程仓库" class="headerlink" title="3.配置远程仓库"></a>3.配置远程仓库</h2><p>打开前面创建的blog目录下的 <strong>_config.yml</strong> 文件,在修改最下方的<strong>deploy</strong>为:(<strong>注意,冒号后面一定要加空格</strong>)</p><pre><code>deploy: type: git repo: [email protected]:ouyang-can/blog.github.io.git(这里填ssh链接) branch: main(这里不要写master了,那是老版本)</code></pre><p>下来安装hexo的git部署,在命令行中执行:</p><pre><code>$ npm install hexo-deployer-git --save</code></pre><p>最后,将生成静态页面并部署到github的仓库中,执行:</p><pre><code>$ hexo d -g 或者$ hexo generate$ hexo deploy</code></pre><p>当提示 <strong>INFO Deploy done: git</strong> 即上传成功,这时就可以通过仓库地址来访问你的个人站点了。<br> <span class="lazyload-img-span"> <img data-src="https://raw.githubusercontent.com/MagicTmac1/Picture_repo/master/202207110007057.png" > </sapn> </p><h3 id="常用Hexo命令"><a href="#常用Hexo命令" class="headerlink" title="常用Hexo命令"></a>常用Hexo命令</h3><pre><code>hexo init //在指定目录执行该命令,会将当前目录初始化为hexo站点,生成hexo站点所需的一切文件hexo new “my new blog title” //新建一篇文章。如果没有设置 layout 的话,默认使用 _config.yml 中的 hexo new page <pagename> //新建一个网页。生成网页后的路径会在终端中有提示default_layout 参数代替。如果标题包含空格的话,请使用引号括起来。hexo clean // 清除缓存,如果对本地文件做了修改,同步到远程验证修改的效果之前,先clean,清除缓存hexo generate // 可以简写成hexo g 根据markdown文件生成静态文件hexo server // 或者简写成hexo s 启动本地hexo 服务器,默认localhost:4000可以访问hexo deploy // 或者简写成hexo d 将本地修改,部署到远端hexo version // 显示hexo版本</code></pre>]]></content>
<categories>
<category> 博客搭建 </category>
</categories>
<tags>
<tag> blog </tag>
</tags>
</entry>
</search>