大家好,我是哪吒,最近專案在使用MongoDB作為圖片和檔案的儲存資料庫,為啥不直接存MySQL裡,還要搭個MongoDB叢集,麻不麻煩?
讓我們一起,一探究竟,瞭解一下MongoDB的特點和基本用法,實現快速入門,豐富個人簡歷,提高面試level,給自己增加一點談資,秒變面試小達人,BAT不是夢
。
三分鐘你將學會:
農民工
增刪改查MongoDB是一款開源、跨平臺、分散式,具有巨量資料處理能力的檔案儲存資料庫。
檔案資料庫MongoDB用於記錄檔案結構的資料,比如JSON、XML結構的資料。
WiredTiger引擎
、MMAPv1引擎
是基於硬碟讀寫的儲存引擎,In-Memory引擎
是基於記憶體的儲存引擎;MongoDB目前只支援單檔案事務,MongoDB暫時不適合需要複雜事務的場景。
靈活的檔案模型JSON格式儲存最接近真實物件模型,對開發者友好,方便快速開發迭代,可用複製集滿足資料高可靠、高可用的需求,運維較為簡單、故障自動切換可延伸分片叢集海量資料儲存。
傳統的關係型資料庫在解決三高問題上的力不從心。
何為三高?
MongoDB可以完美解決三高問題。
(1)遊戲場景
使用MongoDB儲存遊戲使用者資訊、裝備、積分等,直接以內嵌檔案的形式儲存,方便查詢、更新。
(2)物流場景
使用MongoDB儲存訂單資訊、訂單狀態、物流資訊,訂單狀態在運送過程中飛速迭代、以MongoDB內嵌陣列的形式來儲存,一次查詢就能將訂單所有的變更查出來,牛逼plus。
(3)社交場景
使用MongoDB儲存使用者資訊,朋友圈資訊,通過地理位置索引實現附近的人、定位功能。
(4)物聯網場景
使用MongoDB儲存裝置資訊、裝置彙報的紀錄檔資訊、並對這些資訊進行多維度分析。
(5)視訊直播
使用MongoDB儲存使用者資訊、點贊互動資訊。
MySQL | MongoDB | 解釋說明 |
---|---|---|
database | database | 資料庫 |
table | collection | 表/集合 |
row | document | 行/檔案 |
column | field | 欄位/域 |
index | index | 索引 |
join | 嵌入檔案 | 表關聯/MongoDB不支援join,MongoDB通過嵌入式檔案來替代多表連線 |
primary key | primary key | 主鍵/MongoDB自動將_id欄位設定為主鍵 |
集合就是一組檔案。可以看作是具有動態模式的表。
集合具有動態模式的特性。這意味著一個集合中的檔案可以具有任意數量的不同形態。
但是,將不同型別的檔案存放在一個集合中會出現很多問題:
\0
(空字元),因為這個字元用於表示一個集合名稱的結束;system.
開頭,該字首是為內部集合保留的。檔案是MongoDB中的基本資料單元,相當於傳統關係型資料庫中的行,它是一組有序鍵值的集合。每個檔案都有一個特殊的鍵「_id」,其在所屬的集合中是唯一的。
檔案中的鍵是字串型別。
鍵中不能含有\0(空字元)。這個字元用於表示一個鍵的結束。
.和$是特殊字元,只能在某些特定情況下使用。通常情況下,可以認為這兩個字元是MongoDB的保留字元,如果使用不當,那麼驅動程式將無法正常工作。
資料庫會使用遊標返回find的執行結果。遊標的使用者端實現通常能夠在很大程度上對查詢的最終輸出進行控制。你可以限制結果的數量,跳過一些結果,按任意方向的任意鍵組合對結果進行排序,以及執行許多其他功能強大的操作。
通過cursor.hasNext()
檢查是否還有其它結果,通過cursor.next()
用來對其進行獲取。
呼叫find()時,shell並不會立即查詢資料庫,而是等到真正開始請求結果時才傳送查詢,這樣可以在執行之前給查詢附加額外的選項。cursor物件的大多數方法會返回遊標本身,這樣就可以按照任意順序將選項連結起來了。
在使用db.users.find();
查詢時,實際上查詢並沒有真正執行,只是在構造查詢,執行cursor.hasNext()
,查詢才會發往伺服器端。shell會立刻獲取前100個結果或者前4MB的資料(兩者之中的較小者),這樣下次呼叫next或者hasNext時就不必再次連線伺服器去獲取結果了。在使用者端遍歷完第一組結果後,shell會再次連線資料庫,使用getMore請求更多的結果。getMore請求包含一個遊標的識別符號,它會向資料庫詢問是否還有更多的結果,如果有則返回下一批結果。這個過程會一直持續,直到遊標耗盡或者結果被全部返回。
在伺服器端,遊標會佔用記憶體和資源。一旦遊標遍歷完結果之後,或者使用者端傳送一條訊息要求終止,資料庫就可以釋放它正在使用的資源。
何時銷燬遊標:
https://www.mongodb.com/try/download/community2
D:\Program Files\MongoDB\Server\5.0\bin
D:\Program Files\MongoDB\Server\5.0\bin
,開啟cmd,輸入MongoDB下載zip檔案,解壓,在bin同級目錄下建data資料夾,在data下建一個db資料夾,儲存MongoDB資料。
在bin資料夾下執行cmd,執行mongod --dbpath D:\Program Files\mongodb\data\db
命令;
再在data目錄下,建一個logs資料夾,存放MongoDB紀錄檔。
在mongodb/bin目錄下,建一個mongod.cfg
檔案,寫入
systemLog:
destination: file
logAppend: true
path: D:\Program Files\mongodb\data\logs\mongod.log
storage:
dbPath: D:\Program Files\mongodb\data\db
執行mongod --config "D:\Program Files\mongodb\bin\mongod.cfg" --install
命令,安裝MongoDB。
通過mongod --version
檢查MongoDB版本。
D:\Program Files\mongodb\bin>mongod --version
db version v5.0.14
Build Info: {
"version": "5.0.14",
"gitVersion": "1b3b0073a0b436a8a502b612f24fb2bd572772e5",
"modules": [],
"allocator": "tcmalloc",
"environment": {
"distmod": "windows",
"distarch": "x86_64",
"target_arch": "x86_64"
}
}
突然間,mongodb無法連線了?mongod.exe --dbpath "D:\Program Files\mongodb\data
完美解決。
注意一點,在重新啟動時,執行mongod.exe --dbpath "D:\Program Files\mongodb\data
的視窗不要關閉。
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.8.2</version>
</dependency>
package com.example.demo.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.bson.Document;
import org.bson.conversions.Bson;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
public class MongoDBUtil {
private static MongoClient mongoClient;
private static MongoClient mongoClientIdentify;
/**
* 不通過認證獲取連線資料庫物件
*/
public static MongoDatabase getNoIdentifyConnect(String host, int port, String dbaseName) {
// 連線mongodb服務
MongoDBUtil.mongoClient = new MongoClient(host, port);
// 連線資料庫
MongoDatabase mongoDatabase = MongoDBUtil.mongoClient.getDatabase(dbaseName);
// 返回連線資料庫物件
return mongoDatabase;
}
/**
* 通過連線認證獲取MongoDB連線
*/
public static MongoDatabase getIdentifyConnect(String host, int port, String dbaseName, String userName, String password) {
List<ServerAddress> adds = new ArrayList<ServerAddress>();
ServerAddress serverAddress = new ServerAddress(host, port);
adds.add(serverAddress);
List<MongoCredential> credentials = new ArrayList<>();
MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(userName, dbaseName, password.toCharArray());
credentials.add(mongoCredential);
// 通過連線認證獲取MongoDB連線
MongoDBUtil.mongoClientIdentify = new MongoClient(adds, credentials);
MongoDatabase mongoDatabase = MongoDBUtil.mongoClientIdentify.getDatabase(dbaseName);
return mongoDatabase;
}
/**
* 關閉連線
*/
public static void closeNoIdentifyConnect () {
MongoDBUtil.mongoClient.close();
}
/**
* 關閉連線
*/
public static void closeIdentifyConnect () {
MongoDBUtil.mongoClientIdentify.close();
}
/**
* 插入一個檔案
*/
public static void insertOne (Map<String, Object> data, MongoDatabase mongoDatabase, String col) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
//建立檔案
Document document = new Document();
for (Map.Entry<String, Object> m : data.entrySet()) {
document.append(m.getKey(), m.getValue()).append(m.getKey(), m.getValue());
}
//插入一個檔案
collection.insertOne(document);
}
/**
* 插入多個檔案
*/
public static void insertMany (List<Map<String, Object>> listData, MongoDatabase mongoDatabase, String col) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
//要插入的資料
List<Document> list = new ArrayList<>();
for (Map<String, Object> data : listData) {
//建立檔案
Document document = new Document();
for (Map.Entry<String, Object> m : data.entrySet()) {
document.append(m.getKey(), m.getValue());
}
list.add(document);
}
//插入多個檔案
collection.insertMany(list);
}
/**
* 刪除匹配到的第一個檔案
*/
public static void delectOne (String col, String key, Object value, MongoDatabase mongoDatabase) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
//申明刪除條件
Bson filter = Filters.eq(key, value);
//刪除與篩選器匹配的單個檔案
collection.deleteOne(filter);
}
/**
* 刪除匹配的所有檔案
*/
public static void deleteMany (String col, String key, Object value, MongoDatabase mongoDatabase) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
//申明刪除條件
Bson filter = Filters.eq(key, value);
//刪除與篩選器匹配的所有檔案
collection.deleteMany(filter);
}
/**
* 刪除集合中所有檔案
*/
public static void deleteAllDocument(String col, MongoDatabase mongoDatabase) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
collection.deleteMany(new Document());
}
/**
* 刪除檔案和集合。
*/
public static void deleteAllCollection(String col, MongoDatabase mongoDatabase) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
collection.drop();
}
/**
* 修改單個檔案,修改過濾器篩選出的第一個檔案
*
* @param col 修改的集合
* @param key 修改條件的鍵
* @param value 修改條件的值
* @param eqKey 要修改的鍵,如果eqKey不存在,則新增記錄
* @param eqValue 要修改的值
* @param mongoDatabase 連線資料庫物件
*/
public static void updateOne (String col, String key, Object value,String eqKey, Object eqValue, MongoDatabase mongoDatabase) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
//修改過濾器
Bson filter = Filters.eq(key, value);
//指定修改的更新檔案
Document document = new Document("$set", new Document(eqKey, eqValue));
//修改單個檔案
collection.updateOne(filter, document);
}
/**
* 修改多個檔案
*
* @param col 修改的集合
* @param key 修改條件的鍵
* @param value 修改條件的值
* @param eqKey 要修改的鍵,如果eqKey不存在,則新增記錄
* @param eqValue 要修改的值
* @param mongoDatabase 連線資料庫物件
*/
public static void updateMany (String col, String key, Object value, String eqKey, Object eqValue, MongoDatabase mongoDatabase) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
//修改過濾器
Bson filter = Filters.eq(key, value);
//指定修改的更新檔案
Document document = new Document("$set", new Document(eqKey, eqValue));
//修改多個檔案
collection.updateMany(filter, document);
}
/**
* 查詢集合中的所有檔案
*/
public static MongoCursor<Document> find (String col, MongoDatabase mongoDatabase) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
//查詢集合中的所有檔案
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> cursorIterator = findIterable.iterator();
return cursorIterator;
}
/**
* 按條件查詢集合中檔案
*/
public static MongoCursor<Document> Filterfind (String col,String key, Object value, MongoDatabase mongoDatabase) {
//獲取集合
MongoCollection<Document> collection = mongoDatabase.getCollection(col);
//指定查詢過濾器
Bson filter = Filters.eq(key, value);
//指定查詢過濾器查詢
FindIterable<Document> findIterable = collection.find(filter);
MongoCursor<Document> cursorIterator = findIterable.iterator();
return cursorIterator;
}
}
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
package com.example.demo.utils;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MongoDBTest {
// 獲取資料庫連線物件
MongoDatabase mongoDatabase = MongoDBUtil.getNoIdentifyConnect("127.0.0.1", 27017, "test");
@Test
public void insertOne() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("姓名", "哪吒程式設計");
map.put("性別", "男");
map.put("年齡", 18);
MongoDBUtil.insertOne(map, mongoDatabase, "worker");
MongoDBUtil.closeNoIdentifyConnect();
}
@Test
public void insertMany() {
Map<String, Object> map1 = new HashMap<String, Object>();
map1.put("姓名", "哪吒程式設計2");
map1.put("性別", "男");
map1.put("年齡", 18);
Map<String, Object> map2 = new HashMap<String, Object>();
map2.put("姓名", "妲己");
map2.put("性別", "女");
map2.put("年齡", 18);
List<Map<String, Object>> listData = new ArrayList<>();
listData.add(map1);
listData.add(map2);
MongoDBUtil.insertMany(listData, mongoDatabase, "worker");
MongoDBUtil.closeNoIdentifyConnect();
}
@Test
public void delectOne() {
MongoDBUtil.delectOne("worker", "姓名", "妲己", mongoDatabase);
MongoDBUtil.closeNoIdentifyConnect();
}
@Test
public void deleteMany() {
MongoDBUtil.deleteMany("worker", "姓名", "哪吒程式設計", mongoDatabase);
MongoDBUtil.deleteMany("worker", "姓名", "妲己", mongoDatabase);
MongoDBUtil.closeNoIdentifyConnect();
}
@Test
public void deleteAllDocument() {
MongoDBUtil.deleteAllDocument("worker", mongoDatabase);
MongoDBUtil.closeNoIdentifyConnect();
}
@Test
public void deleteAllCollection() {
MongoDBUtil.deleteAllCollection("worker", mongoDatabase);
MongoDBUtil.closeNoIdentifyConnect();
}
@Test
public void updateOne() {
MongoDBUtil.updateOne("worker", "姓名", "哪吒程式設計2","姓名", "哪吒程式設計", mongoDatabase);
MongoDBUtil.closeNoIdentifyConnect();
}
@Test
public void updateMany() {
MongoDBUtil.updateMany("worker", "姓名", "哪吒程式設計2","姓名", "哪吒程式設計", mongoDatabase);
MongoDBUtil.closeNoIdentifyConnect();
}
@Test
public void find() {
MongoCursor<Document> mongoCursor = MongoDBUtil.find("worker", mongoDatabase);
while (mongoCursor.hasNext()) {
Document document = mongoCursor.next();
System.out.println(document + " size: " + document.size());
}
MongoDBUtil.closeNoIdentifyConnect();
}
@Test
public void filterfind() {
MongoCursor<Document> mongoCursor = MongoDBUtil.Filterfind("worker", "姓名", "哪吒程式設計", mongoDatabase);
while (mongoCursor.hasNext()) {
Document document = mongoCursor.next();
System.out.println(document + " size: " + document.size());
}
MongoDBUtil.closeNoIdentifyConnect();
}
}