mongoDB知識總結


官方說明文檔:https://docs.mongodb.com/manual/mongo/

1 NoSQL 簡介

NoSQL,全稱是”Not Only Sql”,指的是非關系型的數據庫(相對於關系型數據庫RDBMS)。這類數據庫主要有這些特點:非關系型的、分布式的、開源的、水平可擴展的。

NOSQL數據庫相對於關系型數據庫主要解決的問題包括:

l  對數據庫高並發讀寫的需求(High performance)

l  對海量數據的高效率儲存和訪問的需求(Huge Storage)

l  對數據庫的高擴展性和高可用性的需求(High Scalability&&High vailability)

2 MongoDB 基礎知識

mongoDB是一種開源的文檔數據庫系統,開發語言為C++。它提供了一種高效的面向文檔的存儲結構,同時支持通過MapReduce程序來處理所存儲的文檔;它的擴展性很好,而且支持自動分區。Mapreduce可以用來實現數據聚合。它的數據以BSON(二進制JSON)格式存儲,在存儲結構上支持動態schema,並且允許動態查詢。和RDBMS的SQL查詢不同,Mongo查詢語言以JSON表示。

MongoDB是一個面向集合的,模式自由的文檔型數據庫。

面向集合Collenction-Orented,是指數據被分組存儲在數據集中,每個集合在數據庫中都有一個唯一的標識名,並且可以包含無限數目的文檔。類似關系型數據庫RDBMS里的表(table,不同的是它不需要定義任何模式schema)

模式自由schema-free)意味着對於存儲在MongoDB 數據庫中的文件,我們不需要知道它的任何結構定義。

文檔型,存儲的數據是鍵-值對的集合,鍵是字符串,值可以是數據類型集合里的任意類型, 這種數據格式被稱作 “BSON” 即 “Binary Serialized dOcumentNotation.”

2.1 數據邏輯結構

²  MongoDB 的文檔(document),相當於關系數據庫中的一行記錄。

²  多個文檔組成一個集合(collection),相當於關系數據庫的表。

²  多個集合(collection),邏輯上組織在一起,就是數據庫(database)。

²  一個MongoDB 實例支持多個數據庫(database)。

邏輯結構對比

MongoDB

SQL

文檔(document

行(row)

集合(collection

表(table)

數據庫(database

數據庫(database)

2.2 數據庫的安裝、啟動和關閉

數據庫的安裝很簡單,一路next即可。

數據庫的啟動:默認端口27017,默認HTTP端口28017

(在環境變量中創建path路徑C:\Program Files\MongoDB\Server\3.2\bin,這樣可以在C:\workspace路徑下命令行打開,不用輸儲存數據路徑)

l  命令行方式啟動

       在安裝路徑bin目錄下下打開命令行,輸入下列語句:

C:\Program Files\MongoDB\Server\3.2\bin>mongod dbpath C:\workspace\database

l  配置文件打開:

一般數據庫啟動時會有很多參數,為了方便,可以把配置參數放入配置文件然后打開。

  1. 在bin目錄下創建一個mongodb.cnf文件,文件內容如下:

dbpath = C:\workspace\database

  1. 在bin目錄下的命令行中輸入下列命令:
C:\Program Files\MongoDB\Server\3.2\bin>mongod -f mongodb.cnf

l  Daemon方式打開(只能在Linux中使用,我們使用創建window服務方法代替)

(Daemon程序是一直運行的服務器程序,被稱為守護進程,通常作為系統服務在后台運行,沒有終端,不能和前台交互,在系統開啟時啟動在系統關閉后關閉)

在上兩種方式中都需要打開一個命令行窗口,一旦窗口關閉,服務隨之停止。所以為了使服務在窗口關閉之后能繼續使用,我們可以添加一個fork參數。需要注意的是在添加fork參數的同時應該添加logpath參數,這是強制性的。

C:\Program Files\MongoDB\Server\3.2\bin>mongod dbpath  C:\workspace\database fork logpath C:\workspace\database\log\r3.log

同上文標注的一樣,這種方法實際上只能在Linux系統中使用,windows系統中無法使用這種方法,但是作為一種變通,我們可以將mongoDB作為windows服務來啟動。

方法如下:

  1. 1.       首先在C:\workspace路徑下創建databaselog文件夾,在log文件夾下創建mongo.log文件
  2. 在bin目錄下打開命令行輸入下列語句
  3. 在創建服務成功后,在命令行中繼續輸入
C:\Program Files\MongoDB\Server\3.2\bin> mongod -dbpath c:\workspace\database --logpath c:\workspace\log\mongo.log --install --serviceName "MongoDB"
C:\Program Files\MongoDB\Server\3.2\bin>net start mongodb

可以看到命令行中打印出來mongoDB服務已經啟動成功。

數據庫的關閉:

如果使用的是前兩中的數據庫啟動方法

  1. 在命令行窗口下按ctrl+C
  2. 在命令行窗口中輸入指令db.shutdownServer()
C:\Program Files\MongoDB\Server\3.2\bin>db.shutdownServer()

使用windows服務啟動的方法

  1. 關閉服務,在bin目錄下打開命令行輸入

C:\Program Files\MongoDB\Server\3.2\bin>net stop mongodb

  1. 刪除服務,在bin目錄下打開命令行輸入

C:\Program Files\MongoDB\Server\3.2\bin> mongod -dbpath c:\workspace\database --logpath c:\workspace\log\mongo.log --remove --serviceName "MongoDB"

  1. 輸入啟動命令可以看到命令行中打出 “服務名無效的提示”

2.3數據庫的訪問控制

訪問控制一般是考慮到安全方面的因素,在開發環境中通常不用設置,但在生產環境中需要仔細考慮。訪問控制包含三個方面:IP綁定,設置監聽端口,使用用戶名和口令登陸

l  綁定IP內網地址

添加一個bind_ip參數即可實現綁定

>mongod --bind_ip 114.114.114.114 -dbpath D:\mongoDB\data

在綁定內網后,客戶端訪問時必須輸入服務端的ip,否則報錯,如

>mongo 172.168.18.11

l  設置監聽端口

官方默認的端口為27017,為了避免惡意連接,可以修改端口,添加-port參數

>mongod --bind_ip 114.114.114.114port 28018 -dbpath D:\mongoDB\data

同樣客戶端在訪問時需要添加端口號

>mongo 172.168.18.11:28018

l  使用用戶名和密碼登錄

在服務端啟動時添加auth參數即可開啟登陸驗證模塊

> mongod -dbpath D:\mongoDB\data -auth

但是,如果我們的admin.system.users中沒有添加任何用戶時,登陸驗證模塊是沒有用的,直到我們添加了一個用戶。

> db.addUser("root","111")

這時,我們輸入命令查看驗證

> db.auth("root","111")

這時如果我們如果想操作數據庫就需要輸入用戶名和密碼了

> mongou root -p

3 MongoDB的操作

下面的所有操作都需要在啟動mongoDB服務的情況下進行,同時這些操作都可以使用圖形化工具運行,這里使用的是robomongo工具。

3.1 連接數據庫

如果我們想進入數據庫后台管理部分,我們需要進入bin目錄下,打開命令行輸入mongo命令:

C:\Program Files\MongoDB\Server\3.2\bin>mongo

命令行會提醒connect  to本地數據庫中的test數據庫。

3.2 創建和刪除數據庫

假設我們創建一個名為Sample的數據庫,輸入use Sample命令

>use Sample

我們可以使用show dbs命令查看所有的數據庫

>show dbs

這時並沒有發現我們新建的數據庫,這是因為新建的數據庫沒有數據,我們需要向里面插入數據才會顯示,我們插入一段數據:

>db.Sample.insert({name:"Sample"})

然后在show dbs命令下就能看到我們新建的數據庫了

同時,如果我們需要切換數據庫,我們也可以使用use+數據庫名的命令

如果我們想要刪除這個數據庫,我們可以使用db.dropDatabase()命令

  1. 首先使用show dbs命令顯示所有的數據庫

>show dbs

  1. 使用use命令指向這個數據庫

>use Sample

  1. 使用db.dropDatabase命令刪除這個數據庫

>db.dropDatabase()

注意事項:有些數據庫的名稱是保留的,可以直接訪問

admin: 從權限的角度來看,這是"root"數據庫。要是將一個用戶添加到這個數據庫,這個用戶自動繼承所有數據庫的權限。一些特定的服務器端命令也只能從這個數據庫運行,比如列出所有的數據庫或者關閉服務器。

local: 這個數據永遠不會被復制,可以用來存儲限於本地單台服務器的任意集合

config: 當Mongo用於分片設置時,config數據庫在內部使用,用於保存分片的相關信息。

3.3文檔的增刪改查

假如我們對Sample數據庫進行增刪改查的操作,首先使用use命令定位到該數據庫。

文檔的插入:db.Sample.insert(),括號里面是插入的內容

>db.Sample.insert({name:"Sample"})

也可以先用變量定義文檔內容,然后直接插入,如:

>document = {title:Sample}

>db.Sample.insert(document)

文檔的查看:db.Sample.find()

> db.Sample.find()

這個方法返回的是一串非結構化的數據

通常我們可以使用db.Sample.find().pretty()方法來返回結構化數據

find方法里面可以插入參數來作為查找條件.

  1. 1.  AND條件:db.Sample.find({key1:value1,key2:value2}).pretty()
  2. 2.  OR條件:db.Sample.find({$or:{key1:value1,key2:value2} }).pretty()
  3. 3.  ANGOR條件同時使用:

db.Sample.find({

key1:value1, $or:{key1:value1,key2:value2}

}).pretty()

l  文檔的更新:

1.    使用update方法:    db.Sample.update(),前面的是查詢的條件,后面的是替換的內容

> db.Sample.update({name:"Sample"},{$set:{name:"Samples"}})

 Update()函數主要是用於已經存在數據的更新,下面介紹了他的參數及各個參數的作用。

db.Sample.update(
   <query>,       //查詢條件
   <update>,      //更新的對象及操作符
   {
     upsert: <boolean>,  //可選 truefalse,如果值不存在判斷是否插入
     multi: <boolean>,   //可選 truefalse,默認為false,只更新找到的第一個記錄,true為更新找到的全部記錄
     writeConcern: <document>   //可選 拋出異常的級別
   }
)

2. 使用save()方法通過傳入新的文檔來替代原有文檔

> db.Sample.save(document{ writeConcern: <document>})

l  文檔的刪除操作

建議:在執行刪除操作前先用find()方法來判斷條件是否正確

使用remove()方法:

> db.Sample.remove({name:"Sample"})

 

db.collection.remove(
   <query>,   //查詢條件
   {
     justOne: <boolean>, //可選,true為只刪除一條數據
     writeConcern: <document>   //可選,拋出異常的級別
   }
)

3.4 操作符與limitskip方法

數據庫的操作符包括條件操作符和$type操作符

條件操作符

格式

含義

格式

含義

$gt

大於(>

$gte

大於等於(>=

$lt

小於(<

$lte

小於等於(<=)

使用方法如下:

查找number值大於100的文檔

> db.Sample.find({number:{$gt:10}})

查找number值大於100小於200的文檔

> db.Sample.find({number:{$gt:10$lt:20}})

$type操作符

此方法是根據BSON數據格式來檢索集合中匹配的數據,格式如下:

> db.Sample.find({number:{$type:2}})

$type的值是跟表中類型對應的數字。如下

類型

數字

備注

Double

1

 

String

2

 

Object

3

 

Array

4

 

Binary data

5

 

Undefined

6

已廢棄。

Object id

7

 

Boolean

8

 

Date

9

 

Null

10

 

Regular Expression

11

 

JavaScript

13

 

Symbol

14

 

JavaScript (with scope)

15

 

32-bit integer

16

 

Timestamp

17

 

64-bit integer

18

 

Min key

255

Query with -1.

Max key

127

 

類型

數字

備注

Double

1

 

String

2

 

Object

3

 

Array

4

 

Binary data

5

 

Undefined

6

已廢棄。

Object id

7

 

Boolean

8

 

Date

9

 

Null

10

 

Regular Expression

11

 

JavaScript

13

 

Symbol

14

 

JavaScript (with scope)

15

 

32-bit integer

16

 

Timestamp

17

 

64-bit integer

18

 

Min key

255

Query with -1.

Max key

127

 

Limit()方法:限制查找到數據的個數

> db.Sample.find().Limit(3)

限制查找到數據的值為三個

Skip()方法:跳過制定數量的數據

> db.Sample.find().skip(3)

查找到的數據跳過3

$exists方法:查找字段是否存在

> db.Sample.find({number:{$exists:true}})

這種方法可以用來判斷數據值為null還是不存在。例如查找rollbackTime類的值為null的文檔

> db.Sample.find({rollbackTime:{$in:[null],$exists:true}})

其中$in為查找內容(include的縮寫),必須是數組

$mod方法:取模運算

> db.Sample.find({number:{$mod:[5,0]}})

查找number中模50的值

$ne方法:不等於

> db.Sample.find({number:{$ne:11}})

查找number中不等於11的值

$in方法:包含

> db.Sample.find({number:{$in:[11,12]}})

查找number中等於11,12的值

$nin方法是同樣的用法,意為不包含

$size方法:數組元素的格式

> db.Sample.find({something:{$size:3}})

查找something中數組長度為3的項

對指定字段進行排序

> db.Sample.find().sort({number:1})

根據number字段進行排序,1代表正序,-1代表倒序

3.5 正則表達式匹配

MongoDB數據庫的查詢用到的是js的語法,所以可以使用正則表達式進行匹配

> db.Sample.find ({reason:{$not:/^h.*/}})

查找reason中不以h開頭的項

3.6數據庫的索引和聚合

索引(涉及性能優化部分)

索引是一種特殊的數據結構,存在一個易於讀取的數據結構中,它是對數據庫中一個或多個值進行排序的一種結構,創建索引的格式如下:

> db.Sample.ensureIndex({key1:1key2-1})

Key為要創建的索引字段,1代表的是按升序創建,2代表降序創建

Parameter

Type

Description

background

Boolean

建索引過程會阻塞其它數據庫操作,background可指定以后台方式創建索引,即增加 "background" 可選參數。 "background" 默認值為false

unique

Boolean

建立的索引是否唯一。指定為true創建唯一索引。默認值為false.

name

string

索引的名稱。如果未指定,MongoDB的通過連接索引的字段名和排序順序生成一個索引名稱。

dropDups

Boolean

在建立唯一索引時是否刪除重復記錄,指定 true 創建唯一索引。默認值為 false.

sparse

Boolean

對文檔中不存在的字段數據不啟用索引;這個參數需要特別注意,如果設置為true的話,在索引字段中不會查詢出不包含對應字段的文檔.。默認值為 false.

expireAfterSeconds

integer

指定一個以秒為單位的數值,完成 TTL設定,設定集合的生存時間。

v

index version

索引的版本號。默認的索引版本取決於mongod創建索引時運行的版本。

weights

document

索引權重值,數值在 1 到 99,999 之間,表示該索引相對於其他索引字段的得分權重。

default_language

string

對於文本索引,該參數決定了停用詞及詞干和詞器的規則的列表。 默認為英語

language_override

string

對於文本索引,該參數指定了包含在文檔中的字段名,語言覆蓋默認的language,默認值為 language.

例如我們創建一個索引

> db.Sample.ensureIndex({number:1})

如果我們想在后台創建索引的話,只需要加個參數background:true

> db.Sample.ensureIndex({number:1},{background:true})

查看已創建的索引

> db.Sample.getIndexes()

數據庫聚合方法(mapReduce,進行並行統計

聚合的方法主要是用來處理數據(如求平均值,求和等),並返回處理結果

> db.Sample.aggregate([options])

這個方法里面使用了管道的概念,即將當前命令的結果作為下個命令的參數

表達式

描述

$sum

計算總和

$avg

計算平均值

$min

獲得文檔對應值中最小值

$max

獲得文檔對應值中最大值

$push

在結果文檔中插一個值到數組中

$addToSet

在結果文檔中插入一個值到數組中

$first

根據排序獲得第一個文檔數據

$last

根據排序獲得最后一個文檔數據

聚合框架中常用的幾個操作:

$project

修改輸入文檔的結構,可以用來重命名增加或刪除與,也可以用於創建計算結果以及嵌套文檔

$match

用於過濾數據,只輸出符合條件的文檔

$limit

用來限制MongoDB聚合管道返回的文檔數

$skip

在聚合管道中跳過制定數量的文檔,並返回余下的文檔

$unwind

將文檔中的某一個數組類型子墩拆分,每條包含數組中的一個值

$group

將集合中的文檔分組,用於統計結果

$sort

將輸出文檔排序后輸出

$geoNear

輸出接近某一地理位置的文檔

例如:

> db.Sample.aggregate(([{$match:{number:{$gte:5,$lte:16}}},{$skip:1},

{$project:{_id:0,devSN:1}}]))

其中聚合操作先匹配number值大於5小於16,在得出的結果中跳過第一個,執行下面的修改文檔結構工作

3.7其他操作

l  Count查詢記錄的條數

在find后面加上count方法可以顯示查找到的數據的個數,比如

> db.Sample.find ({reason:{$not:/^h.*/}}).count()

l  Skip可以用來限制返回記錄的起點

> db.Sample.find().skip(2).limit(3)

表示查詢到的數據跳過兩條,顯示三條

l  查看活動進程,了解系統正在干什么

> db.currentOp()

顯示結果中參數的含義:

Opid

操作進程號

Op

操作類型(查詢,更新等)

Ns

命名空間,指操作對象

Query

顯示查詢操作中的具體內容

lockType

指明是讀鎖還是寫鎖

l  結束進程

> db.killOp(1234)

1234為opid

4存儲過程

MongoDB支持儲存過程,並且可以在儲存過程中自定義處理數據,使用的是JavaScript語法。數據庫的存儲過程是在db.system.js表里面的。方法如下:

  1. 首先將自定義的方法轉化為存儲過程

> db.system.js.save({_id:"get_counts",value:function(){return db.Sample.count();}})

這里添加了一個get_counts的方法,value的值就是方法的具體內容,可以使用find方法查看過程是否被儲存

> db.system.js.find()

  1. 使用eval函數來調用自定義的方法(eval函數里面也可以直接定義並調用方法)

> db.eval('get_counts')

5 GridFS:MongoDB存儲大型文件的規范

由於MongoDB中BSON對象的大小是有限制的,所以采用GridFS規范來將一個大文件分隔成多個小文件,使得數據庫可以存儲視頻,高清圖片之類的大文件。這個規范支持Java,Perl,PHP,Python,Ruby等程序

5.1 簡介

GridFS使用兩個表來存儲數據:

  1. files包含元數據對象
  2. chunks包含相關信息的二進制塊

為保證多個GridFS命名為一個單一的數據庫,文件和塊都有一個前綴,默認為fs,所以任何的GridFS存儲都會包括fs.files和fs.chunks。前綴fs可以被修改。

5.2 使用方法

我們以存入一個pdf文檔為例,

C:\Program Files\MongoDB\Server\3.2\bin>mongofiles -d Sample put Redis.pdf

-d參數指定的是數據庫名稱,如果沒有,會自動增加一個名為test的數據庫。

我們可以查看一下數據庫中有哪些GridFS文件

C:\Program Files\MongoDB\Server\3.2\bin>mongofiles list

同時也可以使用find命令查看文件內容

C:\Program Files\MongoDB\Server\3.2\bin>db.fs.files.find()

6 Mapreduce計算模型

將大批量的工作分解(MAP)執行,再將結果合並(reduce)成最終的結果。可以用來構建大型的復雜的聚合查詢

它命令的基本語法是:

>db.collection.mapReduce(
   function() {emit(key,value);},  //map 函數
   function(key,values) {return reduceFunction},   //reduce 函數
   {
      out: collection,//統計結果存放集合,不指定則使用臨時集合
      query: document,//篩選條件
      sort: document,//排序函數
      limit: number//限制發往map函數的文檔數量
   }
)

例如:我們現在要找到number值相同的_id

  1. 1.  首先寫map函數

> var m=function(){emit(this.number ,this._id);};

其中_id是要統計的數據,number為分組的依據,map函數實現的是分組功能

  1. 2.  編寫reduce函數

> var r=function(key,values){var ret={ _id:key, number:value};return ret;};

這里reduce函數處理分組后的數據

  1. 3.  編寫finalize函數

> var f=function(values,rval){if(value!=0){rval.msg="success";}return rval};

f函數用來做最后的處理

  1. 4.  運行函數

>  db.runCommand({mapreduce:"Sample",map:m,reduce:r,finalize:f})

  1. 5.  使用find函數來查詢處理后的結果

> db.Sample.find()

結果參數:

result:儲存結果的collection的名字,這是個臨時集合,MapReduce的連接關閉后自動就被刪除了。

timeMillis:執行花費的時間,毫秒為單位

input:滿足條件被發送到map函數的文檔個數

emit:在map函數中emit被調用的次數,也就是所有集合中的數據總量

ouput:結果集合中的文檔個數count對調試非常有幫助)

ok:是否成功,成功為1

 

7 MongoDB工具

MongoDB數據庫暗轉目錄下有幾個工具可以進行導入導出及備份恢復的功能。

包括:

mongo.exe    客戶端程序,連接MongoDB

mongod.exe  服務端程序,啟動MongoDB

mongo.exe    備份程序

mongoexport.exe 數據導出程序

mongofiles.exe    GridFS工具,內建的分布式文件系統

mongostat.exe      狀態監測工具,固定時間獲取數據庫的運行狀態。

mongotop.exe      默認返回每個集合每一秒讀入寫出的狀態

mongoimport.exe        數據導入程序

mongorestore.exe       數據恢復程序

mongos.exe  數據分片程序,支持數據的橫向擴展

mongodump.exe  備份程序

bsondump.exe     用於將導出的bson格式轉變成json格式

mongoperf.exe    獨立檢查數據庫I/O性能的工具

7.1    GUI工具

MongoDB有很多的GUI管理工具:

l  MongoVUE  主頁:http://www.mongovue.com/

l  RockMongo      主頁:http://code.google.com/p/rock-php/

l  MongoHub       主頁:https://github.com/bububa/MongoHub

l  Robomongo     主頁:https://robomongo.org/

我用的是robomongo

7.2    監控

在mongoDB中有兩種自帶的監控工具來監控數據庫的運行情況

l  工具mongostat

間隔固定時間獲取數據庫當前的運行狀態

C:\Program Files\MongoDB\Server\3.2\bin>mongostat

l  工具mongotop

獲取每一個集合每一秒讀取寫入的信息

C:\Program Files\MongoDB\Server\3.2\bin>mongotop

可以在命令后面跟一個數字作為參數(sleeptime)來設定獲取信息的時間間隔

命令行打印信息參數含義:

ns

數據庫的名稱和集合

Total

在這個集合中操作花費的時間總和

Read

讀入操作花費的時間

Write

寫入操作花費的時間

 

7.3    數據導入和導出

輸入命令中各個參數的含義:

-d :數據庫名稱               -c:集合名稱             --csv是數據格式csv        

-f :指名導出那些類        -o:導出文件的名稱

l  數據導入:mongoimport

導入JSON數據

C:\Program Files\MongoDB\Server\3.2\bin>mongoimport -d Sample -c Sample C:\workspace\Sample.json

導入csv格式數據

C:\Program Files\MongoDB\Server\3.2\bin>mongoimport -d Sample -c Sample --type csv -headerline -file C:\workspace\test.csv

其中,--type 指定的是導入數據的格式,-headerline指的是忽略導入數據的第一行(因為是類),-file指的是導入文件的路徑。

l  數據導出:mongoexport工具

C:\Program Files\MongoDB\Server\3.2\bin>mongoexport -d Sample -c Sample -o Sample.dat

我們可以查看導出的文件,可以發現是JSON格式的。同理我們可以導出csv格式的數據。

C:\Program Files\MongoDB\Server\3.2\bin>mongoexport -d devlogserver -c devlog --csv -f _id,devlog,syncTime -o Sample.dat

7.4    數據備份和恢復

l  數據備份:mongodump

C:\Program Files\MongoDB\Server\3.2\bin>mongodump -d WLAN

這個命令會創建一個dump文件夾,備份的文件都放在這個文件夾里,也可以指定-o參數,將備份文件放入指定文件夾

l  數據恢復:mongorestore

數據恢復分為兩種情況:原數據已刪除和原數據未刪除

實際操作中直接執行mongorestore命令即可恢復dump中的數據庫

  1. 源數據已刪除

C:\Program Files\MongoDB\Server\3.2\bin>mongorestore -d WLAN

  1. 原數據未刪除,在上個命令中加入-drop參數

C:\Program Files\MongoDB\Server\3.2\bin>mongorestore -d WLAN -drop C:\Program Files\MongoDB\Server\3.2\bin\dump\WLAN


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM