MongoDB基礎知識(一)
互聯網行業的發展非常的迅速,數據存儲以及架構優化方面也有很多不同的解決方案,例如關系型數據庫、非關系型數據庫、數據倉庫技術等。更多數據庫類產品的出現,為我們很好的解決了數據存儲的問題,例如Redis緩存,MySQL關系型數據庫,MongoDB文檔型數據庫,Hbase數據倉庫等。
隨著業務的發展,在對架構優化時,選取了MongoDB存儲一部分數據,作為一個運維人員只能迎頭趕上,去學習操作和維護相關知識。下面的文檔就是自己學習MongoDB數據庫的學習筆記,主要有以下特點:
1、理論較少,主要是實際操作,
2、和關系型數據庫MySQL對比學習,主要是一些操作方面。俗話說沒有對比,就沒有傷害,兩個不同類型的數據庫對比學習,會更好的提高學習效率。
一、庫的操作
MySQL與MongoDB在 庫、表、數據等概念上有以下差異,MySQL中有數據庫Database,表 table,數據行列等概念,而MongoDB中沒有表和行列等概念,主要包含數據庫Database,集合collections,以及文檔。
RDBMS vs NoSQL
RDBMS
- 高度組織化結構化數據
- 結構化查詢語言(SQL) (SQL)
- 數據和關系都存儲在單獨的表中。
- 數據操縱語言,數據定義語言
- 嚴格的一致性
- 基礎事務
NoSQL
- 代表著不僅僅是SQL
- 沒有聲明性查詢語言
- 沒有預定義的模式
-鍵 - 值對存儲,列存儲,文檔存儲,圖形數據庫
- 最終一致性,而非ACID屬性
- CAP定理
- 高性能,高可用性和可伸縮性
1.1 查看所有數據庫(已經存在)
#MySQL mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | winner | +--------------------+ 4 rows in set (0.04 sec) #MongoDB [[email protected]
註意事項:
在MongoDB裏面,連接數據庫服務端時,在不指定數據庫名時。默認test庫,而MySQL默認是空,當我們切換到具體數據庫時,才能看到具體的當前數據庫信息。
1.2切換數據庫
在切換數據庫時,命令都是使用use + 庫名,但是兩者之間還是有比較大的區別,MongoDB中,如果沒有輸入的庫名,它會創建一個庫名,而MySQL在所有當前庫中,沒有你輸入的數據庫名時,會報錯。
> show dbs col 0.203125GB local 0.078125GB test 0.203125GB winner2 0.203125GB > use win switched to db win > db win #MySQL mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | winner | +--------------------+ 4 rows in set (0.00 sec) mysql> use win; ERROR 1049 (42000): Unknown database ‘win‘ mysql>
1.3創建數據庫
MongoDB沒有具體的創建數據庫的命令,一般在切換的過程中,如果不存在該數據庫,就會新建數據庫,而MySQL中有create database databasename語句創建數據庫。
mysql> use win; ERROR 1049 (42000): Unknown database ‘win‘ #未創建前 mysql> create database win; #創建語句 一般我們創建時 還會指定字符集什麽的 Query OK, 1 row affected (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | win | | winner | +--------------------+ 5 rows in set (0.00 sec) MongoDB use DATABASE_NAME 如果數據庫不存在,則創建數據庫,否則切換到指定數據庫。
1.4 刪除數據庫
剛學完創建和切換,創建後,我們又不想要它了,所以我們考慮一下如何刪除呢???MongoDB中用db.dropDatabase()刪除當前庫,而MySQL中使用 drop database databasename;刪除你要刪除的庫。
MySQL mysql> create database winner2; #創建庫 Query OK, 1 row affected (0.00 sec) mysql> use winner2; #切換庫 Database changed mysql> select database(); #查看當前庫 +------------+ | database() | +------------+ | winner2 | +------------+ 1 row in set (0.00 sec) mysql> drop database winner2; #刪除winner2 Query OK, 0 rows affected (0.00 sec) mysql> select database(); #查看當前庫 +------------+ | database() | +------------+ | NULL | +------------+ 1 row in set (0.00 sec) MongoDB use winner2 #創建winner庫 switched to db winner2 show dbs;#查看當前所有的庫 col 0.203125GB winner2 0.203125GB db #查看當前庫 winner2 MySQL中刪除某個當前庫後,再次查看當前庫是NULL,而MongoDB中刪除當前庫後,仍然顯示當前庫 db.dropDatabase() #刪除當前庫 { "dropped" : "winner2", "ok" : 1 } > db 檢查當前庫 winner2 show dbs#檢查所有的庫 col 0.203125GB >
2、表與集合操作
在我們學習過數據庫相關理論知識後,我們都知道數據是存儲在表中,而數據庫是用來存儲數據表的。而MongoDB和MySQL的表概念是不一樣的,MongoDB是將文檔數據存儲在集合(collection)中,而MySQL是將數據存儲在表(table)中,集合是沒有表的結構的,而表是有相關的結構,例如字段、字段類型、索引、主鍵、存儲引擎等。
2.1 查看當前所有表
#MySQL mysql> use mysql Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +---------------------------+ | Tables_in_mysql | +---------------------------+ | columns_priv | | db | | event | | func | | general_log | | help_category | | help_keyword | | help_relation | | help_topic | | innodb_index_stats | | innodb_table_stats | #MongoDB show dbs col 0.203125GB > use col switched to db col > show collections system.indexes winner winner2 >
2.2 創建表或者集合
MySQL數據是存儲在相關的表中,而MongoDB數據是存儲在集合中,MySQL由於支持插件式存儲引擎,字段類型、索引、主鍵、等原因,讓其創建表結構的語句比較復雜,在應用系統中,性能優化等情況和表結構息息相關。而MongoDB主要是用來存儲key(values)類型的數據,所以要簡單很多。
mysql> use winner Database changed mysql> show tables -> ; Empty set (0.00 sec) mysql> create table winer(id int not null primary key auto_increment, -> name varchar(20) not null , -> age tinyint not null, -> sex tinyint not null default ‘0‘) engine=innodb charset utf8; Query OK, 0 rows affected (0.24 sec) mysql> desc winer; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | NO | | NULL | | | age | tinyint(4) | NO | | NULL | | | sex | tinyint(4) | NO | | 0 | | +-------+-------------+------+-----+ #MongoDB創建集合 在MongoDB中,要操作一個集合,並不需要先創建它。可以直接往集合裏面插入數據,如果集合不存在, 會自動創建集合,並插入數據。
2.3 表與集合的增刪改查
在知道了如何創建一個表、集合等相關知識後,我們就要想著如何對表或者集合數據做修改,而我們的應用系統、業務系統中存儲的數據主要就是增刪改查等相關的操作。
2.3.1插入數據
MySQL中插入數據
創建表SQL語句
CREATE TABLE `winer` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `age` tinyint(4) NOT NULL, `sex` tinyint(4) NOT NULL DEFAULT ‘0‘, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 表結構 mysql> desc winer -> ; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | NO | | NULL | | | age | tinyint(4) | NO | | NULL | | | sex | tinyint(4) | NO | | 0 | | +-------+-------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec)
1、插入單條數據
mysql> insert into winer (name,age,sex) values("MySQL",20,1) -> ; Query OK, 1 row affected (0.09 sec) mysql> select * from winer; +----+-------+-----+-----+ | id | name | age | sex | +----+-------+-----+-----+ | 1 | MySQL | 20 | 1 | +----+-------+-----+-----+ 1 row in set (0.00 sec)
2、批量插入
mysql> insert into winer (name,age,sex) value("MySQL",20,1),("Docker",8,0) -> ; Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into winer (name,age,sex) values("MySQL",20,1),("Docker",8,0) -> ; Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 兩個插入語句之間區別value和values兩者都能插入單個值或者批量值 mysql> select * from winer; +----+--------+-----+-----+ | id | name | age | sex | +----+--------+-----+-----+ | 1 | MySQL | 20 | 1 | | 2 | MySQL | 20 | 1 | | 3 | Docker | 8 | 0 | | 4 | MySQL | 20 | 1 | | 5 | Docker | 8 | 0 | +----+--------+-----+-----+ 5 rows in set (0.00 sec)
3、其他插入數據的方法
MySQL中除了傳統的insert into插入數據外,我們還可以用load data mysqlimport等方式導入數據,也可以將其他表中的數據插入到某張表中,具體方法不做詳細描述。
2.3.2 MongoDB中插入數據
MongoDB主要存儲的是文檔數據,文檔的數據結構和JSON基本一樣。所有存儲在集合中的數據都是BSON格式。BSON是一種類json的一種二進制形式的存儲格式,簡稱Binary JSON。
插入文檔
MongoDB 使用 insert() 或 save() 方法向集合中插入文檔,語法如下:
db.COLLECTION_NAME.insert(document) db.COLLECTION_NAME.save(document)
1、簡單的插入
db.winner.find() #插入前 MongoDB中用find查看以前的數據類似mysql中的select > db.winner.insert({name:"linux"}) #插入結果 >db.winner.find() { "_id" : ObjectId("592bf6bf1b8e279c43cbb021"), "name" : "linux" } >
2、定義變量
> SQLNAME=({"titile":"MongoDB學習實踐", description: "MongoDB是NoSQL數據庫", by:"書籍學習"}) 可以將我們要插入的數據定義成變量,後面使用加載變量的方式來實現數據的插入 > db.sql.insert(SQLNAME) > db.sql.find() { "_id" : ObjectId("592bf8b5f3fed7ab45761fc1"), "titile" : "MongoDB學習實踐", "description" : "MongoDB是NoSQL數據庫", "by" : "書籍學習" } >
3、for循環插入
MongoDB還支持for(i=0;i<100;i++)db.winner2.insert({x:i})這種形式的數據插入。 for(i=0;i<100;i++)db.winner2.insert({x:i})for(i=0;i<100;i++)db.winner2.insert({x:i}) > db.winner2.find()db.winner2.find() { "_id" : ObjectId("592bfaa425e6a2cd19372da3"), "x" : 0 } { "_id" : ObjectId("592bfaa425e6a2cd19372da4"), "x" : 1 } { "_id" : ObjectId("592bfaa425e6a2cd19372da5"), "x" : 2 } { "_id" : ObjectId("592bfaa425e6a2cd19372da6"), "x" : 3 } { "_id" : ObjectId("592bfaa425e6a2cd19372da7"), "x" : 4 } { "_id" : ObjectId("592bfaa425e6a2cd19372da8"), "x" : 5 } { "_id" : ObjectId("592bfaa425e6a2cd19372da9"), "x" : 6 } { "_id" : ObjectId("592bfaa425e6a2cd19372daa"), "x" : 7 } { "_id" : ObjectId("592bfaa425e6a2cd19372dab"), "x" : 8 } { "_id" : ObjectId("592bfaa425e6a2cd19372dac"), "x" : 9 } { "_id" : ObjectId("592bfaa425e6a2cd19372dad"), "x" : 10 } { "_id" : ObjectId("592bfaa425e6a2cd19372dae"), "x" : 11 } { "_id" : ObjectId("592bfaa425e6a2cd19372daf"), "x" : 12 } { "_id" : ObjectId("592bfaa425e6a2cd19372db0"), "x" : 13 } { "_id" : ObjectId("592bfaa425e6a2cd19372db1"), "x" : 14 } { "_id" : ObjectId("592bfaa425e6a2cd19372db2"), "x" : 15 } { "_id" : ObjectId("592bfaa425e6a2cd19372db3"), "x" : 16 } { "_id" : ObjectId("592bfaa425e6a2cd19372db4"), "x" : 17 } { "_id" : ObjectId("592bfaa425e6a2cd19372db5"), "x" : 18 } #db.winner2.count() #統計數據條數 類似MySQL中的 select count(*) from tablename where * 100
2.3.3刪除數據
1、MySQL中刪除數據
MySQL中刪除數據最常用的是delete結合where子句的方式,在清空表的時候可用truncate,delete不加限制條件時時刪除整個表的數據,但是當表中存在自增主鍵列時,新增加的數據主鍵自增列不會從初始化數字開始,而是從之前被刪除的位置繼續,而truncate是清空表,對整個表中的自增主鍵列重新初始化。
mysql> select count(*) from winer; +----------+ | count(*) | +----------+ | 160 | +----------+ 1 row in set (0.03 sec) mysql> select * from winer limit 10; +----+--------+-----+-----+ | id | name | age | sex | +----+--------+-----+-----+ | 1 | MySQL | 20 | 1 | | 2 | MySQL | 20 | 1 | | 3 | Docker | 8 | 0 | | 4 | MySQL | 20 | 1 | | 5 | Docker | 8 | 0 | | 6 | MySQL | 20 | 1 | | 7 | MySQL | 20 | 1 | | 8 | Docker | 8 | 0 | | 9 | MySQL | 20 | 1 | | 10 | Docker | 8 | 0 | +----+--------+-----+-----+ 10 rows in set (0.00 sec) 用delete刪除全部數據 mysql> delete from winer; Query OK, 160 rows affected (0.01 sec) 再插入數據 mysql> insert into winer (name,age,sex) select name,age,sex from winner2; Query OK, 5 rows affected (0.01 sec) Records: 5 Duplicates: 0 Warnings: 0 #檢查數據的主鍵情況,確實是從之前的刪除前開始存儲的,而並不是重新開始。 mysql> select * from winer; +-----+--------+-----+-----+ | id | name | age | sex | +-----+--------+-----+-----+ | 249 | MySQL | 20 | 1 | | 250 | MySQL | 20 | 1 | | 251 | Docker | 8 | 0 | | 252 | MySQL | 20 | 1 | | 253 | Docker | 8 | 0 | +-----+--------+-----+-----+ 5 rows in set (0.00 sec) truncate 刪除檢查 mysql> truncate winer; Query OK, 0 rows affected (0.09 sec) mysql> insert into winer (name,age,sex) select name,age,sex from winner2; Query OK, 5 rows affected (0.01 sec) Records: 5 Duplicates: 0 Warnings: 0 mysql> select * from winer; +----+--------+-----+-----+ | id | name | age | sex | +----+--------+-----+-----+ | 1 | MySQL | 20 | 1 | | 2 | MySQL | 20 | 1 | | 3 | Docker | 8 | 0 | | 4 | MySQL | 20 | 1 | | 5 | Docker | 8 | 0 | +----+--------+-----+-----+ 5 rows in set (0.00 sec) 主鍵從1開始。 truncate 釋放存儲表數據所用的數據頁來刪除數據,並且只在事務日誌中記錄頁的釋放
2、MongoDB中刪除數據
MongoDB remove()函數是用來移除集合中的數據。在執行remove()函數前先執行find()命令來判斷執行的條件是否正確,這是一個比較好的習慣。數據的刪除應該是一個很嚴謹的操作,不能隨意的操作,無論是MySQL還是MongoDB,或者其他的數據庫,我們都應該養成這樣的良好習慣。嚴格條件限制、備份、謹慎等。
remove() 方法的基本語法格式如下所示: db.collection.remove( <query>, <justOne> ) MongoDB 是 2.6 版本以後的,語法格式如下: db.collection.remove( <query>, { justOne: <boolean>, writeConcern: <document> } ) 參數說明: query :(可選)刪除的文檔的條件。 justOne : (可選)如果設為 true 或 1,則只刪除一個文檔。 writeConcern :(可選)拋出異常的級別
根據篩選條件 刪除部分數據 > db.winner.find()db.winner.find() { "_id" : ObjectId("592c2e01c070fc0df2f50f09"), "x" : 0 } { "_id" : ObjectId("592c2e01c070fc0df2f50f0b"), "x" : 2 } { "_id" : ObjectId("592c2e01c070fc0df2f50f0c"), "x" : 3 } { "_id" : ObjectId("592c2e01c070fc0df2f50f0d"), "x" : 4 } { "_id" : ObjectId("592c2e01c070fc0df2f50f0e"), "x" : 5 } { "_id" : ObjectId("592c2e01c070fc0df2f50f0f"), "x" : 6 } { "_id" : ObjectId("592c2e01c070fc0df2f50f10"), "x" : 7 } { "_id" : ObjectId("592c2e01c070fc0df2f50f11"), "x" : 8 } { "_id" : ObjectId("592c2e01c070fc0df2f50f12"), "x" : 9 } { "_id" : ObjectId("592c2e01c070fc0df2f50f13"), "x" : 10 } { "_id" : ObjectId("592c2e01c070fc0df2f50f14"), "x" : 11 } { "_id" : ObjectId("592c2e01c070fc0df2f50f15"), "x" : 12 } { "_id" : ObjectId("592c2e01c070fc0df2f50f16"), "x" : 13 } { "_id" : ObjectId("592c2e01c070fc0df2f50f17"), "x" : 14 } { "_id" : ObjectId("592c2e01c070fc0df2f50f18"), "x" : 15 } { "_id" : ObjectId("592c2e01c070fc0df2f50f19"), "x" : 16 } { "_id" : ObjectId("592c2e01c070fc0df2f50f1a"), "x" : 17 } { "_id" : ObjectId("592c2e01c070fc0df2f50f1b"), "x" : 18 } { "_id" : ObjectId("592c2e01c070fc0df2f50f1c"), "x" : 19 } { "_id" : ObjectId("592c2e01c070fc0df2f50f1d"), "x" : 20 } Type "it" for more > db.winnerdb.winne.remove({x:20}) > db.winedb.winne.find({x:20}) 刪除全部 db.winner.remove() db.winner.find() show tables;#檢查集合 或者使用show collections system.indexes win_collection winer winner 由於MongoDB裏面的集合不像MySQL裏面的表還有結構什麽的,所以當我們刪除所有數據時,可以直接 刪除整個集合,當下次插入數據時,又會創建一個新的集合。 db.winner.drop() > for(i=0;i<100;i++)db.winner.insert({x:i})for(i=0;i<100;i++)db.winner.insert({x:i}) > db.winner.find()db.winner.find() { "_id" : ObjectId("592c34bd17c668d64f637dab"), "x" : 25 } { "_id" : ObjectId("592c34bd17c668d64f637dac"), "x" : 26 } { "_id" : ObjectId("592c34bd17c668d64f637dad"), "x" : 27 } { "_id" : ObjectId("592c34bd17c668d64f637dae"), "x" : 28 } { "_id" : ObjectId("592c34bd17c668d64f637daf"), "x" : 29 } { "_id" : ObjectId("592c34bd17c668d64f637db0"), "x" : 30 } { "_id" : ObjectId("592c34bd17c668d64f637db1"), "x" : 31 } > db.winner.drop() true > db.winner.find() > show tables; system.indexes win_collection winer 經過對比,已經刪除了之前的集合,但是這樣的刪除不會影響我們後面插入數據。
刪除重復文檔中的一條文檔 定義變量 SQLNAME=({"titile":"MongoDB學習實踐", description: "MongoDB是NoSQL數據庫", by:"書籍學習"}) 增加數據: >db.winner2.insert(SQLNAME) >db.winner2.insert(SQLNAME) >db.winner2.insert(SQLNAME) >db.winner2.find() #檢查所有的數據 { "_id" : ObjectId("592c3628c1e073e087a335ee"), "titile" : "MongoDB學習實踐", "description" : "MongoDB是NoSQL數據庫", "by" : "書籍學習" } { "_id" : ObjectId("592c362ac1e073e087a335ef"), "titile" : "MongoDB學習實踐", "description" : "MongoDB是NoSQL數據庫", "by" : "書籍學習" } { "_id" : ObjectId("592c3639c1e073e087a335f0"), "titile" : "MongoDB學習實踐", "description" : "MongoDB是NoSQL數據庫", "by" : "書籍學習" } > 執行刪除 db.winner2.remove({"titile" : "MongoDB學習實踐"}) 再次檢查 所有的結果全部刪除 db.winner2.find() > 結合前面的語法 db.winner2.remove({"titile" : "MongoDB學習實踐"},1) 再查看數據只刪除了其中的一部分 db.winner2.find() { "_id" : ObjectId("592c391b30de16129bcc9310"), "titile" : "MongoDB學習實踐", "description" : "MongoDB是NoSQL數據庫", "by" : "書籍學習" } { "_id" : ObjectId("592c391c30de16129bcc9311"), "titile" : "MongoDB學習實踐", "description" : "MongoDB是NoSQL數據庫", "by" : "書籍學習" }
2.3.4 更改數據
MySQL中更改數據主要通過update table set where之類的語句實現,做一個簡單的示例,不做詳細的描述。
mysql> select * from winner2; +----+--------+-----+-----+ | id | name | age | sex | +----+--------+-----+-----+ | 1 | MySQL | 20 | 1 | | 2 | MySQL | 20 | 1 | | 3 | Docker | 8 | 0 | | 4 | MySQL | 20 | 1 | | 5 | Docker | 8 | 0 | +----+--------+-----+-----+ 5 rows in set (0.00 sec) mysql> update winner2 set name="MySQLDBA" where id=2; #將id為2的name更改為MySQLDBA Query OK, 1 row affected (0.03 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from winner2; +----+----------+-----+-----+ | id | name | age | sex | +----+----------+-----+-----+ | 1 | MySQL | 20 | 1 | | 2 | MySQLDBA | 20 | 1 | | 3 | Docker | 8 | 0 | | 4 | MySQL | 20 | 1 | | 5 | Docker | 8 | 0 | +----+----------+-----+-----+ 5 rows in set (0.00 sec)
MongoDB中的數據更改也是通過update() 和 save() 實現的,需要註意的是,update()默認更改適合條件的一條文檔記錄。
update() 和 save()
update() 方法用於更新已存在的文檔。語法格式如下:
db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> } )
參數說明:
query : update的查詢條件,類似sql update查詢內where後面的。
update : update的對象和一些更新的操作符(如$,$inc...)等,也可以理解為sql update查詢內set後面的
upsert : 可選,這個參數的意思是,如果不存在update的記錄,是否插入objNew,true為插入,默認是false,不插入。
multi : 可選,mongodb 默認是false,只更新找到的第一條記錄,如果這個參數為true,就把按條件查出來多條記錄全部更新。
writeConcern :可選,拋出異常的級別。
save() 方法
save() 方法通過傳入的文檔來替換已有文檔。語法格式如下: db.collection.save( <document>, { writeConcern: <document> } )
參數說明:
document : 文檔數據。
writeConcern :可選,拋出異常的級別。
更多實例
只更新第一條記錄:
db.col.update( { "count" : { $gt : 1 } } , { $set : { "test2" : "OK"} } ); 全部更新: db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} },false,true ); 只添加第一條: db.col.update( { "count" : { $gt : 4 } } , { $set : { "test5" : "OK"} },true,false ); 全部添加加進去: db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} },true,true ); 全部更新: db.col.update( { "count" : { $gt : 15 } } , { $inc : { "count" : 1} },false,true ); 只更新第一條記錄: db.col.update( { "count" : { $gt : 10 } } , { $inc : { "count" : 1} },false,false );
MongoDB基礎知識(一)