MangoDB高級應用

来源:https://www.cnblogs.com/SimpleWu/archive/2018/11/24/10012219.html
-Advertisement-
Play Games

MongoDB高級應用 Author:SimpleWu 聚合 聚合(aggregate)主要用於處理數據(諸如統計平均值,求和等),並返回計算後的數據結果。有點類似sql語句中的 count( )。 $group 使用$group是對篩選的數據進行分組。類似於mysql中的group by關鍵字。 ...


MongoDB高級應用

Author:SimpleWu

聚合

聚合(aggregate)主要用於處理數據(諸如統計平均值,求和等),並返回計算後的數據結果。有點類似sql語句中的 count(*)。

//統計員工總數
db.emp.aggregate([{$count:"countName"}])
//或者
db.emp.find().count()

$group

使用$group是對篩選的數據進行分組。類似於mysql中的group by關鍵字。

//根據員工gender來分組並且統計數量
db.emp.aggregate([{$group : {_id : "$gender", count: {$sum : 1}}}])

說明:

  • 這裡_id是表示分組的欄位,名字是固定的。
  • count表示聚合生成列的名稱。
  • $sum表示聚合函數。
  • 1統計的值,其他聚合函數也可以是欄位。

聚合表達式

表達式 描述 實例
$sum 計算總和。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
$avg 計算平均值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$min 獲取集合中所有文檔對應值得最小值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$max 獲取集合中所有文檔對應值得最大值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push 在結果文檔中插入值到一個數組中。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet 在結果文檔中插入值到一個數組中,但不創建副本。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first 根據資源文檔的排序獲取第一個文檔數據。 db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$last 根據資源文檔的排序獲取最後一個文檔數據 db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

這些聚合函數基本上與mysql,oracle中效果是一致的。

索引

所以這東西學習過資料庫的都知道是不可缺少的,當然我們的MangoDB也是有的。

索引通常能夠極大的提高查詢的效率,如果沒有索引,MongoDB在讀取數據時必須掃描集合中的每個文檔,並選取那些符合查詢條件的記錄。

創建索引語法:

db.collection.createIndex(keys, options)
/*
key:你要創建的索引欄位,1 為指定按升序創建索引,如果你想按降序來創建索引指定為 -1 即可。如果多個欄位使用,隔開
*/
db.emp.createIndex({"name":1})                    #創建單列索引
db.emp.createIndex({"name":1,"age":-1})      #創建多列索引。

索引的常見操作

//查看集合索引
db.emp.getIndexes()
//查看集合索引大小
db.emp.totalIndexSize()
//刪除集合所有索引
db.emp.dropIndexes()
//刪除集合指定索引
db.emp.dropIndex("索引名稱")

索引的種類

在mysql裡面索引有許多種類當然我們的MongoDB中也有很多種類:id索引、單鍵索引、多鍵索引、複合索引、過期索引、全文索引。

id索引

ID索引也稱為主鍵索引,是我們創建一個集合時,自動創建的索引。

集合的預設排序是按照id來進行排序的。在mongodb中id是根據ObjectId()來生成的,這個順序是以時間撮來進行生成。

單鍵索引

單鍵索引是最普通的索引。

和id索引不同,單鍵索引不會自動創建,需要我們手動創建。

db.col.createIndex({"name":1})//創建單列索引,對name列創建索引

多鍵索引

多鍵索引和單鍵索引創建形式相同,區別在於欄位的值。

單鍵索引:值是一個單一的值,例如:字元串,數字或者日期。

多鍵索引:值有多個記錄,例如:數組。

db.emp.createIndex({"name":1,"age":-1})//創建多列索引,對name和age創建索引

複合索引

當我們的查詢條件不只一個時,就需要建立符合索引。符合索引是在多個列上同時創建索引。

db.col.createIndex({"name":1,"age":-1})  //創建複合索引。

索引的命名

預設情況下,索引的命名是列+1或者-1,這種方式不是很方面記憶,而且刪除是也不太方面。這時候我們就需要為索引創建一個名稱。

//創建索引並命名為ix_name。
db.students.createIndex({name:-1},{name:"ix_name"})

唯一索引

我們可以為索引添加一個唯一性,從而保存該列的數據不允許重覆。

//創建索引並命名為ix_name。
db.students.createIndex({name:-1},{name:"ix_name",unique:true})

過期索引

過期索引:就是在一段時間後會自動過期的索引。在索引過期後,相應的數據也會被刪除。

適合存儲一些希望一段時間後會失效的數據,比如用戶登錄信息,存儲的日誌等。

db.collections.createIndex({time:1},{expireAfterSeconds:10})

過期索引的一些限制:

  • 過期索引的值必須是指定的時間類型,必須使用ISODate或者ISODate數組,不能使用時間撮,否則不會被自動刪除。
  • 如果指定的是ISODate數組,則按照最小時間刪除。
  • 過期索引不能是複合索引。
  • 刪除時間是有一定的誤差,由於刪除過程是由後臺程式每60秒跑一次,而且刪除數據也需要一定的時間。所以存在誤差。

全文索引

當要對一篇文章中的文本內容進行搜索的時候,這個時候可以考慮全文索引。全文索引可以加快檢索內容關鍵字的效率。全文索引只能對字元串或者字元串數組有效。

//創建全文索引
db.students.createIndex({name:"text",info:"text"})

使用全文索引

創建好全文索引後,我們就可以來使用全文索引,使用全文索引需要使用$text和$search兩個運算符。

//查找全文索引中包含了zhangsan的文檔。
db.students.find({$text:{$search:"zhangsan"}})

//查找全文索引中包含了zhangsan或者zhangsanfeng的文檔。
db.students.find({$text:{$search:"zhangsan zhangsanfeng"}})

//查找全文索引中包含了zhangsan,但不包含zhangsanfeng的文檔。
db.students.find({$text:{$search:"zhangsan -zhangsanfeng"}})

//查找全文索引中包含了zhangsan和zhangsanfeng的文檔。
db.students.find({$text:{$search:"\"zhangsan\" \"zhangsanfeng\""}})

全文索引的相似度

我們在百度中搜索時,經常會看到和我們關鍵字匹配度越高的,排行就越靠前。在mongodb中,我們還可以返回查詢結果的相似度,與sort一起使用效果會更好。

使用方式:在find後面跟上{score:{$meta:"textScore"}}

db.students.find({$text:{$search:"zhangsan"}},{score:{$meta:"textScore"}})
.sort({score:{$meta:"textScore"}})

全文索引的限制

  • 每次查詢只能指定一個text。
  • text操作符不能出現在$nor查詢中。
  • 查詢中如果包含了text則hint將不再起作用。
  • mongodb的全文索引對中文支持不是很好。

索引的註意事項

索引像一把雙刃劍,用得好可以提高查詢效率,如果用不好可能會導致性能的降低。

  • $where和$exists完全不能走索引
  • ne取反操作效率很低
  • $not、$nin$or、$in

explain執行計劃

索引的性能如何,我們可以通過explain執行計劃來進行分析,從而使索引的性能達到最優。

explain的使用方式非常簡單,我們只需要在執行的find()命令後添加一個explain()方法即可。

db.students.find().explain();

文檔之間的關係

很多時候資料庫中的數據不是單獨存在的,數據和數據之間會有一些相互之間的聯繫。我們mongodb可以配置這種數據之間的關係。

文檔之間的關係

  • 一對一(one to one)
  • 一對多(one to many)
  • 多對一(many to one)
  • 多對多(many to many)

每種關係又可以有兩種方式來實現。

嵌入式:嵌套在一個document文檔中。

引用式:通過外鍵引用的方式來實現。

Java操作MongoDB

下載MongoDB驅動http://mongodb.github.io/mongo-java-driver/

<dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver</artifactId>
        <version>3.9.0</version>
</dependency>

連接資料庫,你需要指定資料庫名稱,如果指定的資料庫不存在,mongo會自動創建資料庫。

public static void main( String args[] ){
      try{   
         // 連接到 mongodb 服務
         MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
       
         // 連接到資料庫
         MongoDatabase mongoDatabase = mongoClient.getDatabase("students");  
         System.out.println("Connect to database successfully");
        
      }catch(Exception e){
         System.err.println( e.getClass().getName() + ": " + e.getMessage() );
     }
   }

我們可以使用 com.mongodb.client.MongoDatabase 類中的createCollection()來創建集合

我們可以使用com.mongodb.client.MongoCollection類的 insertMany() 方法來插入一個文檔。

我們可以使用 com.mongodb.client.MongoCollection 類中的 find() 方法來獲取集合中的所有文檔。

你可以使用 com.mongodb.client.MongoCollection 類中的 updateMany() 方法來更新集合中的文檔。

要刪除集合中的第一個文檔,首先你需要使用com.mongodb.DBCollection類中的 findOne()方法來獲取第一個文檔,然後使用remove 方法刪除。
個人測試結果,基本操作:

package com.simple.nosql.mongodb;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bson.Document;
import org.junit.Before;
import org.junit.Test;

import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;

/**
 * MangoDB基本操作
 * @author SimpleWu
 *
 */
public class Test1 {

    private MongoClient mongoClient = null;

    /**
     * 獲取MongoDB客戶端連接
     * 
     * @return
     */
    public MongoClient getMongoClient() {
        this.mongoClient = new MongoClient("localhost", 27017);
        return this.mongoClient;
    }

    private MongoDatabase mongoDatabase = null;

    /**
     * 連接資料庫,你需要指定資料庫名稱,如果指定的資料庫不存在,mongo會自動創建資料庫。
     */
    public MongoDatabase createConnection() {
        getMongoClient();// 獲取客戶端連接
        // 連接到資料庫
        mongoDatabase = mongoClient.getDatabase("students");
        System.out.println("Connect to database successfully");
        return this.mongoDatabase;

    }

    @Before
    public void before() {
        createConnection();
    }

    /**
     * 我們可以使用 com.mongodb.client.MongoDatabase 類中的createCollection()來創建集合
     */
    @Test
    public void createCollection() {
        // 創建集合
        mongoDatabase.createCollection("employee");
        System.out.println("集合創建成功");
    }

    /**
     * 獲取集合
     */
    public MongoCollection<Document> getCollection() {
        // 獲取指定名稱集合
        MongoCollection<Document> collection = mongoDatabase.getCollection("employee");
        System.out.println("集合獲取成功");
        return collection;
    }

    /**
     * 插入文檔
     */
    @Test
    public void testInsert() {
        // 獲取集合
        MongoCollection<Document> collection = getCollection();
        Map<String, Object> map = new HashMap<>();
        map.put("_id", 1);
        map.put("name", "AA");
        map.put("email", "[email protected]");
        map.put("info", "my name is AA");
        Document document = new Document(map);
        collection.insertOne(document);

        // 插入多個文檔
        Document document1 = new Document();
        document1.append("_id", 2);
        document1.append("name", "BB");
        document1.append("email", "[email protected]");
        document1.append("info", "my name is BB");
        Document document2 = new Document();
        document2.append("_id", 3);
        document2.append("name", "CC");
        document2.append("email", "[email protected]");
        document2.append("info", "my name is CC");
        List<Document> list = Arrays.asList(document1, document2);
        collection.insertMany(list);
        System.out.println("插入文檔成功");
    }

    /**
     * 檢索文檔
     */
    @Test
    public void testFind() {
        // 獲取集合
        MongoCollection<Document> collection = getCollection();
        
        // 檢索所有文檔
        FindIterable<Document> iterable = collection.find();
        
        //獲取結果集
        MongoCursor<Document> cursor = iterable.iterator();
        while (cursor.hasNext()) {
            System.out.println(cursor.next());
        }

        // 獲取name=AA的文檔
        /*
         * Document document = new Document(); document.append("name", "AA");
         * FindIterable<Document> iterable = collection.find(document);
         * select(iterable);
         */
    }

    /**
     * 更新文檔
     */
    @Test
    public void update() {
        // 獲取集合
        MongoCollection<Document> collection = getCollection();
        //創建需要更新的條件
        Document document = new Document("name", "AA");
        //創建需要更新的內容
        Document upd = new Document("name", "AA-AA");
        //更新文檔
        Document document1 = new Document("$set", upd);
        UpdateResult result = collection.updateOne(document, document1);
        System.out.println("更新成功");
    }
    
    /**
     * 指定條件查詢
     */
    @Test
    public void eqLtGt(){
        MongoCollection<Document> collection = getCollection();
        
        //創建條件
        Document check = new Document("$eq", 1);
        
        //指定判斷列
        Document document1 = new Document("_id",check);
        
        FindIterable<Document> iterable = collection.find(document1);
        
        select(iterable);
    }

    /**
     * 刪除文檔
     */
    @Test
    public void delete() {
        // 獲取集合
        MongoCollection<Document> collection = getCollection();
        
        Document document = new Document("name", "BB");
        
        DeleteResult result = collection.deleteOne(document);
        
        System.out.println("刪除數量 : " + result.getDeletedCount());
    }

        /**
     * 分頁
     */
    @Test
    public void testPage(){
        getMongoClient();// 獲取客戶端連接
        // 連接到資料庫
        mongoDatabase = mongoClient.getDatabase("students");
        // 獲取集合總記錄數
        Long count = mongoDatabase.getCollection("employee").count();
        
        MongoCollection<Document> collection = mongoDatabase.getCollection("employee");
        
        int pageSize = 2;//當前頁
        int pageCount = 10;//每頁文檔數
        //開始頁數,每頁數量。取得結果值
        FindIterable<Document> iterable  = collection.find().skip( (pageSize - 1) *pageCount).limit(pageCount);
        select(iterable);
    }

    public void select(FindIterable<Document> iterable) {
        MongoCursor<Document> cursor = iterable.iterator();
        while (cursor.hasNext()) {
            System.out.println(cursor.next());
        }
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 說明:以下是個人的見解,不一定都正確,如有錯誤,歡迎指正! 一,shell腳本的運行方式,最常見的有以下幾種: 1 ) . xxx.sh,註意,前面是一個點'.' 2 ) source xxx.sh,這種方式和第一種的方式效果是一樣的 3)./xxx.sh 4) sh xxx.sh 5) bash ...
  • 8、修改用戶限制 9、修改用戶驗證選項 10、修改用戶配置文件 11、修改用戶 12、創建目錄 註:雲機器預設無法用ctrl+alt+f7切換至圖形界面,而且無gnom桌面,所以為了識別>256color,進行以下操作 yum groupinstall "X Window System" ##yum ...
  • 1、檢查必要的安裝包是否安裝 命令腳本: rpm -q binutils compat-libstdc++-33 elfutils-libelf elfutils-libelf-devel gcc gcc-c++ glibc glibc-common glibc-devel glibc-header ...
  • 172.18.237.14:一臺主機上安裝LAMP環境以及zabbix_server、zabbix_agentd 一、安裝zibbix-server 1、環境要求 yum install mysql-libs mysql-devel curl-devel gcc gcc-c++ –y 2、編譯安裝 ...
  • 1.軟硬體準備軟體:推薦使用VMwear,我用的是VMwear 10鏡像:CentOS7 硬體:因為是在宿主機上運行虛擬化軟體安裝centos,I3CPU雙核、硬碟500G、記憶體4G以上。 2.虛擬機準備1.打開VMwear選擇新建虛擬機 2.典型安裝與自定義安裝典型安裝:VMwear會將主流的配置 ...
  • Redis概述 1.是一個開源的,先進的<key,value>存儲,並用與構建高性能,可擴展的應用程式的完美解決方案 2.從它的許多競爭繼承來的三個主要特點: l Redis資料庫完全在記憶體中,使用磁碟僅用於持久性。 l 相比許多鍵值數據存儲,Redis擁有一套較為豐富的數據類型。String,Li ...
  • [20181124]關於降序索引問題3.txt--//鏈接:blog.itpub.net/267265/viewspace-2221425/,探討降序索引中索引的鍵值。--//實際上使用函數sys_op_descend.--//鏈接:http://blog.itpub.net/267265/view ...
  • [20181124]關於降序索引問題2.txt--//鏈接:blog.itpub.net/267265/viewspace-2221425/,探討降序索引中索引的鍵值。--//實際上使用函數sys_op_descend.--//前面已經提到結尾加入FF,為了排序的需要。這樣導致chr(0),以及後續 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...