MongoDB 入门到高级简写

  • MongoDB特点

1.支持特别查询

  • MongoDB中,可以通过字段,范围查询进行搜索,并且还支持正则表达式搜索。

2.索引

  • 可以索引文档中的任何字段。

3.复制

  • MongoDB支持主从复制。主机可以执行读写操作,从机从主机复制数据,只能用于读取或备份(不写入)

4.复制数据

  • MongoDB可以在多台服务器上运行。 复制数据以保持系统正常运行,并在硬件故障的情况下保持其运行状态。

5.负载均衡

  • 由于数据放在碎片中,因此具有自动负载平衡配置。

6.支持映射缩减和聚合工具

7.使用JavaScript而不是Procedure

8.它是一个用C++编写的无模式数据库

9.提供高性能

10.轻松存储任何大小的文件,而不会使您的堆栈复杂化

11.在故障的情况下易于管理

12.它还支持:

  • 具有动态模式的JSON数据模型
  • 自动分片用于水平可扩展性
  • 内置复制高可用性

二、安装配置

1.下载安装

Windows上安装 MongoDB,首先打开: http://www.mongodb.org/downloads 下载最新版本的

2.MongoDB配置(mongodb.conf)

#数据库路径

dbpath=C:\Program Files\MongoDB\Server\3.4\data

#日志输出文件路径

logpath=C:\Program Files\MongoDB\Server\3.4\logs\mongo.log

#错误日志采用追加模式

logappend=true

#启用日志文件,默认启用

journal=true

#这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为false

quiet=true

#端口号 默认为27017

port=27017

3.Windows服务配置(mongodb.bat)

--启动MongoDB服务

mongod --config "C:\Program Files\MongoDB\Server\3.4\mongo.conf"

 

--添加启动服务

mongod --config "C:\Program Files\MongoDB\Server\3.4\mongo.conf" --install --serviceName "MongoDB"

 

--添加带权限认证的

mongod --config "C:\Program Files\MongoDB\Server\3.4\mongo.conf"  --auth --install --serviceName "MongoDB"

 

--启动服务

net start MongoDB

 

--删除服务

mongod.exe --remove --serviceName "MongoDB"

 

sc delete MongoDB

 

--

4.用户权限配置(启动后执行mongo.exe)命令

use admin

--创建用户

db.createUser({user:"admin",pwd:"admin",roles:["userAdminAnyDatabase","dbAdminAnyDatabase","root"]})

--创建角色

db.createRole({

    "role": "mongostatRole",

    "privileges": [

        {

            "resource": {

                "cluster": true

            },

            "actions": [

                "serverStatus"

            ]

        }

    ],

    "roles": []

})

--授权用户角色

db.grantRolesToUser("admin",[{role: "mongostatRole",db: "admin"}])

 

--创建其他用户

db.createUser({

    "user": "dba",

    "pwd": "dba",

    "db" : "ucloudlink",

    "roles": [

        {

            "role" : "readWrite",

            "db" : "ucloudlink"

        },

        {

            "role" : "readWrite",

            "db" : "newdb"

        }

    ]

})

 

三、MongoDB数据类型

MongoDB支持许多数据类型。 其中一些是 -

  • 字符串 - 这是用于存储数据的最常用的数据类型。MongoDB中的字符串必须为UTF-8
  • 整型 - 此类型用于存储数值。 整数可以是32位或64位,具体取决于服务器。
  • 布尔类型 - 此类型用于存储布尔值(true / false)值。
  • 双精度浮点数 - 此类型用于存储浮点值。
  • 最小/最大键 - 此类型用于将值与最小和最大BSON元素进行比较。
  • 数组 - 此类型用于将数组或列表或多个值存储到一个键中。
  • 时间戳 - ctimestamp,当文档被修改或添加时,可以方便地进行录制。
  • 对象 - 此数据类型用于嵌入式文档。
  • Null - 此类型用于存储Null值。
  • 符号 - 该数据类型与字符串相同; 但是,通常保留用于使用特定符号类型的语言。
  • 日期 - 此数据类型用于以UNIX时间格式存储当前日期或时间。您可以通过创建日期对象并将日,月,年的日期进行指定自己需要的日期时间。
  • 对象ID - 此数据类型用于存储文档的ID
  • 二进制数据 - 此数据类型用于存储二进制数据。
  • 代码 - 此数据类型用于将JavaScript代码存储到文档中。
  • 正则表达式 - 此数据类型用于存储正则表达式。

 

四、使用MongoDB数据库

1、登录数据库

Mongo

User admin

db.auth(“admin”,”admin”);

show dbs

--带认证的登录

mongo --port 27017 -u "admin" -p "admin" --authenticationDatabase "admin"

2、创建数据库

user newdb

3、删除数据库

db.dropDatabase()

4、创建集合

MongoDB  db.createCollection(nameoptions) 方法用于在MongoDB 中创建集合。

语法

createCollection()命令的基本语法如下 -

db.createCollection(name, options)

在命令中,name 是要创建的集合的名称。 options是一个文档,用于指定集合的配置。

参数

类型

描述

name

String

要创建的集合的名称

options

Document

(可选)指定有关内存大小和索引的选项

options参数是可选的,因此只需要指定集合的名称。 以下是可以使用的选项列表:

字段

类型

描述

capped

Boolean

(可选)如果为true,则启用封闭的集合。上限集合是固定大小的集合,它在达到其最大大小时自动覆盖其最旧的条目。 如果指定true,则还需要指定size参数。

autoIndexId

Boolean

(可选)如果为true,则在_id字段上自动创建索引。默认值为false

size

数字

(可选)指定上限集合的最大大小(以字节为单位) 如果cappedtrue,那么还需要指定此字段的值。

max

数字

(可选)指定上限集合中允许的最大文档数。

在插入文档时,MongoDB首先检查上限集合capped字段的大小,然后检查max字段。

 

5、删除集合

MongoDB  db.collection.drop() 用于从数据库中删除集合。

 

 

6、聚合

6.1、count() 方法

db.article.count();

db.article.count({by_user:"Maxsu"})

6.2、distinct()方法

db.article.distinct('by_user')

db.runCommand({"distinct":"article","key":"by_user"})

 

6.3、aggregate()方法

db.article.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])

 

6.4、group()方法

 

 

7、索引

 

索引支持查询的有效地提高效率。没有索引,MongoDB必须扫描集合的每个文档,以选择与查询语句匹配的文档。这种扫描效率很低,需要 MongoDB 处理大量的数据。

索引是特殊的数据结构,以易于遍历的形式存储数据集的一小部分。 索引存储特定字段或一组字段的值,按照索引中指定的字段值排序。

ensureIndex()方法

要创建索引,需要使用MongoDBensureIndex()方法。

语法

ensureIndex()方法的基本语法如下 -

>db.COLLECTION_NAME.ensureIndex({KEY:1})

这里的key是要在其上创建索引的字段的名称,1是升序。 要按降序创建索引,需要使用-1

示例

>db.mycol.ensureIndex({"title":1})
Shell

ensureIndex()方法中,可以传递多个字段,以在多个字段上创建索引。

>db.mycol.ensureIndex({"title":1,"description":-1})

ensureIndex()方法也接受选项列表(可选) 以下是列表 -

参数

类型

描述

background

Boolean

在后台构建索引,以便构建索引不会阻止其他数据库活动,则指定background的值为true。默认值为false

unique

Boolean

创建一个唯一的索引,使得集合不会接受索引键或键匹配索引中现有值的文档的插入。 指定true以创建唯一索引。 默认值为false

name

String

索引的名称。如果未指定,则MongoDB通过连接索引字段的名称和排序顺序来生成索引名称。

dropDups

Boolean

在可能有重复项的字段上创建唯一索引。MongoDB仅索引第一次出现的键,并从集合中删除包含该键的后续出现的所有文档。指定true以创建唯一索引。 默认值为false

sparse

Boolean

如果为true,则索引仅引用具有指定字段的文档。这些索引在某些情况下(特别是排序)使用的空间较小,但行为不同。默认值为false

expireAfterSeconds

integer

指定一个值(以秒为单位)作为TTL,以控制MongoDB在此集合中保留文档的时间。

v

索引版本

索引版本号。默认索引版本取决于创建索引时运行的MongoDB的版本。

weights

文档

权重是从199999之间的数字,并且表示该字段相对于其他索引字段在分数方面的意义。

default_language

String

对于文本索引,确定停止词列表的语言以及句柄和分词器的规则。 默认值为英文。

language_override

String

对于文本索引,要指定文档中包含覆盖默认语言的字段名称。默认值为language

 

五、MongoDB 监控

1、连接MongoDB

mongo --port 27017 -u "admin" -p "admin" --authenticationDatabase "admin"

2、mongostat

此命令检查所有运行的mongod实例的状态,并返回数据库操作的计数器。 这些计数器包括插入,查询,更新,删除和游标。 命令还显示遇到页面错误,并显示锁定百分比。这可以用来监控内存不足,写入容量或出现性能问题。

 

Mongostat 5 --port 27017 -u "admin" -p "admin" --authenticationDatabase "admin"

 

3、mongotop

此命令跟踪并报告基于集合的 MongoDB 实例的读写活动。 默认情况下,mongotop会在每秒钟内返回信息,但是可相应地更改信息。应该检查此读写活动是否符合您的应用意图,并且要一次对数据库发出太多的写入操作,从磁盘读取的频率太高,或者超出了工作集合大小。

 

mongotop 5 --port 27017 -u "admin" -p "admin" --authenticationDatabase "admin"

 

六、MongoDB关联关系

MongoDB中的关系表示各个文档在逻辑上的相互关联。关系可以通过嵌入式和引用方法建模。 这种关系可以是111NN1NN

假设有一种情况:要存储用户的地址。一个用户可以拥有多个地址,这就是1N关系。

以下是用户(users)文档示例的文档结构 -

{
   "_id":10999110,
   "name": "Maxsu",
   "contact": "13888990021",
   "dob": "1992-10-11"
}

以下是地址(address)文档的示例文档结构 -

{
   "_id":12200,
   "building": "Hainan Building NO.2100",
   "pincode": 571100,
   "city": "Haikou",
   "province": "Hainan"
}

1、嵌入式关系建模

嵌入式方法中,我们将地址(address)文档嵌入到用户(users)文档中。

{
   "_id": 21000100,
   "contact": "13800138000",
   "dob": "1991-11-11",
   "name": "Maxsu",
   "address": [
      {
         "building": "Hainan Building NO.2100",
         "pincode": 571100,
         "city": "Haikou",
         "province": "Hainan"
      },
      {
         "building": "Sanya Building NO.2100",
         "pincode": 572200,
         "city": "Sanya",
         "province": "Hainan"
      },
   ]
}

该方法将所有相关数据保存在单个文档中,这使得检索和维护更容易。可以使用单个查询来在整个文档检索,例如 -

> db.users.findOne({"name":"Maxsu"},{"address":1, "name":1})

请注意,缺点是如果嵌入式文档的大小如果不断增长,可能会影响读/写性能。

2、建模参考关系

这是设计规范化关系的方法。 在这种方法中,用户和地址文件将分别维护,但用户文档将包含一个将引用地址文档的id字段的字段。

{
   "_id":ObjectId("52ffc33321332111sdfaf"),
   "contact": "13800138000",
   "dob": "1991-11-11",
   "name": "Maxsu",
   "address_ids": [
      ObjectId("123123"),
      ObjectId("123412")
   ]
}

如上所示,用户文档包含对应地址的ObjectId的数组字段address_ids 使用这些ObjectIds,我们可以从那里查询地址文件并获取地址详细信息。 使用这种方法,需要两个查询:首先从用户文档获取address_ids字段,然后从地址集中获取这些地址。

>var result = db.users.findOne({"name":"Maxsu"},{"address_ids":1})
>var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})

 

七、MongoDB数据库引用

DBRefs

考虑一个示例场景,在这个场景中将使用DBRefs而不是手动引用,设计有一个数据库中将不同类型的地址(家庭,办公室,邮件等)存储在不同的集合(address_homeaddress_officeaddress_mailing)中。 现在,当用户集合的文档引用地址时,还需要根据地址类型指定要查找的集合。 在这种情况下,文档引用了多个集合中的文档,则应该使用DBRefs

使用DBRefs

DBRefs中有三个字段 -

  • $ref - 此字段指定引用文档的集合
  • $id - 此字段指定引用文档的_id字段
  • $db - 这是一个可选字段,并包含引用文档所在的数据库的名称

假设一个具有DBRef字段address的示例用户文档,如代码片段所示 -

{
   "_id":ObjectId("348362491fjaskdlf2314"),
   "address": {
   "$ref": "address_home",
   "$id": ObjectId("sfaafdf4137832149fssa"),
   "$db": "ucloudlink"},
   "contact": "13800138000",
   "dob": "1991-12-12",
   "name": "Maxsu"
}

这里的 DBRef 字段 address指定引用的地址文件位于ucloudlink数据库中的address_home集合中,其IDsfaafdf4137832149fssa

以下代码由$ref参数(在示例中为address_home)指定的集合中动态地查找IDDBRef中的$id参数指定的文档。

>var user = db.users.findOne({"name":"Maxsu"})
>var dbRef = user.address
>db[dbRef.$ref].findOne({"_id":(dbRef.$id)})

以上代码返回address_home集合中存在的以下address文档中

{
   "_id" : ObjectId("sfaafdf4137832149fssa"),
   "building" : "Hainan Apt No.2100",
   "pincode" : 571100,
   "city" : "Haikou",
   "province" : "Hainan"
}

 

八、Java连接MongoDB操作

 

 

 

九、Mongodb集群搭建

Mongodb的三种集群方式的搭建:Replica Set / Sharding / Master-Slaver

1、Replica Set(副本集

简单来说就是集群当中包含了多份数据,保证主节点挂掉了,备节点能继续提供数据服务,提供的前提就是数据需要和主节点一致。如下图:

 

       Mongodb(M)表示主节点,Mongodb(S)表示备节点,Mongodb(A)表示仲裁节点。主备节点存储数据,仲裁节点不存储数据。客户端同时连接主节点与备节点,不连接仲裁节点。

       默认设置下,主节点提供所有增删查改服务,备节点不提供任何服务。但是可以通过设置使备节点提供查询服务,这样就可以减少主节点的压力,当客户端进行数据查询时,请求自动转到备节点上。这个设置叫做Read Preference Modes,同时Java客户端提供了简单的配置方式,可以不必直接对数据库进行操作。

       仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点。这里虽然只有一个备节点,但是仍然需要一个仲裁节点来提升备节点级别。我开始也不相信必须要有仲裁节点,但是自己也试过没仲裁节点的话,主节点挂了备节点还是备节点,所以咱们还是需要它的。

 

接下来Windows环境创建一个Replica Set副本集):

    1. 建立配置文件

C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs0.conf

C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs1.conf

C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs2.conf

1.2、创建复制集服务

sc.exe create OpenXLive.MongoDB_Ad.Shard_a0 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs0.conf\"" DisplayName= "rs_a0_Service" start= "auto"

sc.exe create OpenXLive.MongoDB_Ad.Shard_a1 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs1.conf\"" DisplayName= "rs_a1_Service" start= "auto"

sc.exe create OpenXLive.MongoDB_Ad.Shard_a2 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs2.conf\"" DisplayName= "rs_a2_Service" start= "auto"

1.3、配置及初始化 Replica Sets

初始化配置,使上面的配置生效

call mongo.exe 127.0.0.1:10000/admin

 

--一个简单的复制集最少包括三个节点。 1.primary 2. secondary,3.arbiter节点

cfg={_id: 'rs_a', members:[{_id:0,host:'127.0.0.1:10000',priority:2}, {_id:1,host:'127.0.0.1:10001',priority:1},{_id:2,host:'127.0.0.1:10002',arbiterOnly:true}]}; 

rs.initiate(cfg);

 

 

查看复制集状态

rs.conf();

rs.status();

primary节点上查看复制集状态:

rs.isMaster()

 

`2、分片集群架构

分片集群主要有mongos路由进程、配置服务器、复制集组成的分片集合组成。 如下图:

 

  • 碎片(Shards) - 碎片用于存储数据。它们提供高可用性和数据一致性。 在生产环境中,每个分片是一个单独的副本集。
  • 配置服务器(Config Servers) - 配置服务器存储集群的元数据。 该数据包含集群的数据集与分片的映射。查询路由器使用此元数据将操作定位到特定的分片。 在生产环境中,分片集群正好有3个配置服务器。
  • 查询路由器(Query Routers) - 查询路由器基本上是 mongo 实例,与客户端应用程序的接口和直接操作到适当的分片。 查询路由器处理并将操作定向到碎片,然后将结果返回给客户端。 分片集群可以包含多个查询路由器来分割客户端请求负载。 客户端向一个查询路由器发送请求。 一般来说,分片集群有许多查询路由器。

 

分片集群上一个分片(shard 就是一个复制集。 当然也可以是一个单个Mongod实例。在集群中一般用复制集。保证一个分片不会故障。如果一个分片出现故障。整个集群就挂了。因为每一个分片上保留数据的一部分。所有分片的综合才是所有数据。所以我们应该保证每个分片上数据的完整性和稳定性至关重要。

Mongos和配置服务器是轻量级进程。是不会保存数据的。 配置服务器只保存分片的一些状态信息。 所以整个读取集群的过程为: 访问Mongos-查询配置服务器,根据配置服务器要求写入或读取那些分片服务器进行读取数据。

 

2.1、创建副本集

创建副本集b、c

2.2、创建配置服务

sc.exe create OpenXLive.MongoDB_Ad.Shard_cfg0 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\configsvr\cfgserver_0.conf"" DisplayName= "rs_cfg0_Service" start= "auto"

sc.exe create OpenXLive.MongoDB_Ad.Shard_cfg1 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\configsvr\cfgserver_1.conf"" DisplayName= "rs_cfg1_Service" start= "auto"

sc.exe create OpenXLive.MongoDB_Ad.Shard_cfg2 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\configsvr\cfgserver_2.conf"" DisplayName= "rs_cfg2_Service" start= "auto"

 

call mongo.exe 127.0.0.1:40000/admin

cfg={_id: 'configs', members:[{_id:0,host:'127.0.0.1:40000'}, {_id:1,host:'127.0.0.1:40001'},{_id:2,host:'127.0.0.1:40002'}]}; 

rs.initiate(cfg);

2.3、创建路由服务

sc.exe create rs_mongosr_Service1 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongos.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\mongos\cfg_mongos.conf"" DisplayName= "rs_mongosr_Service1" start= "auto"

直接启动

mongos --config "C:\Program Files\MongoDB\Server\3.4\cluster\config\mongos\cfg_mongos.conf"

 

 

call mongo.exe 127.0.0.1:50000/admin

db.runCommand({addshard:"rs_a/127.0.0.1:10000,127.0.0.1:10001",name:"ShardSetA"})

db.runCommand({addshard:"rs_b/127.0.0.1:20000,127.0.0.1:20001",name:"ShardSetB"})

db.runCommand({listshards : 1})

printShardingStatus()

 

db.runCommand({"enablesharding":"ucloudlink"})

sh.status()

 

 

十、MongoDB其他高级特性

1、MongoDB原子操作

2、MongoDB高级索引

3、MongoDB Map Reduce

根据MongoDB文档的说明,Map-reduce是将大量数据合并为有用的聚合结果的数据处理范例。 MongoDB使用mapReduce命令进行map-reduce操作。MapReduce通常用于处理大型数据集。

MapReduce命令

以下是基本 mapReduce 命令的语法 -

>db.collection.mapReduce(
   function() {emit(key,value);},  //map function
   function(key,values) {return reduceFunction}, {   //reduce function
      out: collection,
      query: document,
      sort: document,
      limit: number
   }
)

map-reduce函数首先查询集合,然后将结果文档映射到发出的键值对,然后根据具有多个值的键进行减少。

在上面的语法 -

  • map是一个JavaScript函数,它将一个值与一个键映射并发出一个键值对;
  • reduce是一个javascript功能,可以减少或分组具有相同键的所有文档;
  • out指定map-reduce查询结果的位置;
  • query指定选择文档的可选选择条件;
  • sort指定可选的排序条件;
  • limit指定可选的最大文档数;

使用MapReduce

请考虑存储用户帖子的以下文档结构。 该文档存储用户的user_name和帖子的状态(status)

{
   "post_text": "bilin tutorials is an awesome website for tutorials",
   "user_name": "maxsu",
   "status":"active"
}

现在,我们将在posts集上使用mapReduce函数来选择所有status的值为active的帖子,并根据user_name分组,然后使用以下代码对每个用户的帖子数进行计数

>db.posts.mapReduce( 
   function() { emit(this.user_id,1); }, 
   function(key, values) {return Array.sum(values)}, {  
      query:{status:"active"},  
      out:"post_total" 
   }
)

4、MongoDB文本搜索

5. MongoDB正则表达式

正则表达式在所有的编程语言中经常使用,用于以搜索任何字符串中的模式或单词。 MongoDB还提供使用$regex运算符的字符串模式匹配的正则表达式的功能。 MongoDB使用PCRE(Perl兼容正则表达式)作为正则表达式语言。

与文本搜索不同,不需要使用任何配置或命令来使用正则表达式。

请考虑以下文档结构,其中包含post文本及其标签 -

{
   "post_text": "enjoy the mongodb articles on bilin tutorials",
   "tags": [
      "mongodb",
      "bilin"
   ]
}

使用正则表达式

以下regex查询搜索包含bilin字符串的所有帖子 -

>db.posts.find({post_text:{$regex:"bilin"}})

上面的查询也可以写成 -

>db.posts.find({post_text:/bilin/})

使用不区分大小写的正则表达式

要使搜索不区分大小写,可指定$options参数的值为$i 以下命令将寻找具有单词bilin的字符串,不管其是小写还是大写字母 -

>db.posts.find({post_text:{$regex:"bilin", $options:"$i"}})

此查询返回的结果之一是以下文档,其中包含大小写字母的bilin单词 -

{
   "_id" : ObjectId("595b99e1f6a6243715b3c316"),
   "post_text" : "hey! this is my post on Bilin Bilin", 
   "tags" : [ "bilin" ]
},
{
   "_id" : ObjectId("595b99e1f6a6243715b3c317"),
   "post_text" : "hey! this is my post on bilin Bilin", 
   "tags" : [ "bilin" ]
}

对数组元素使用正则表达式

我们也可以在数组字段上使用正则表达式。当实现标签的功能时,这尤其重要。 所以,如果要从单词:tutorial(tutorialtutorials , tutorialpoint  tutorialphp  tutorialpython tutorialphp)开始搜索所有具有标签的帖子,可以使用以下代码 -

> db.posts.find({tags:{$regex:"tutorial"}})

优化正则表达式查询

  • 如果文档字段创建了索引,则查询将使用索引值来匹配正则表达式。 与正常表达式扫描整个集合相比,使用索引值使得搜索非常快。
  • 如果正则表达式是前缀表达式,则所有匹配都是以某个字符串字符开始。 例如,如果正则表达式是^tut,则查询必须仅搜索以tut开头的那些字符串。

6MongoDB自动递增序列

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值