1. 程式人生 > >MongoDB 針對巢狀物件,多層級結構儲存,增刪改查

MongoDB 針對巢狀物件,多層級結構儲存,增刪改查

簡要介紹NOSQL

mongoDB 是屬於NOSQL.什麼是nosql,NoSQL(NoSQL = Not Only SQL ),意即”不僅僅是SQL”。
NoSQL,指的是非關係型的資料庫。NoSQL有時也稱作Not Only SQL的縮寫,是對不同於傳統的關係型資料庫的資料庫管理系統的統稱。

NoSQL用於超大規模資料的儲存。(例如谷歌或Facebook每天為他們的使用者收集萬億位元的資料)。這些型別的資料儲存不需要固定的模式,無需多餘操作就可以橫向擴充套件。
這裡寫圖片描述

mongodb介紹

  • MongoDB的提供了一個面向文件儲存,操作起來比較簡單和容易。你可以在MongoDB記錄中設定任何屬性的索引 (如:FirstName=”Sameer”,Address=”8 Gandhi Road”)來實現更快的排序。
  • 你可以通過本地或者網路建立資料映象,這使得MongoDB有更強的擴充套件性。
  • MongoDb 使用update()命令可以實現替換完成的文件(資料)或者一些指定的資料欄位 。
  • Mongodb中的Map/reduce主要是用來對資料進行批量處理和聚合操作。
  • Map和Reduce。Map函式呼叫emit(key,value)遍歷集合中所有的記錄,將key與value傳給Reduce函式進行處理。
  • Map函式和Reduce函式是使用Javascript編寫的,並可以通過db.runCommand或mapreduce命令來執行MapReduce操作。
  • GridFS是MongoDB中的一個內建功能,可以用於存放大量小檔案。
  • MongoDB允許在服務端執行指令碼,可以用Javascript編寫某個函式,直接在服務端執行,也可以把函式的定義儲存在服務端,下次直接呼叫即可。
  • MongoDB支援各種程式語言:RUBY,PYTHON,JAVA,C++,PHP,C#等多種語言。
  • MongoDB安裝簡單。

spring 整合使用mongodb

我自己使用mongodb ,是用spring 中帶的mongodb包來使用的。只要的jar包是,下面是maven引用包

        <dependency>
            <groupId>org.mongodb</groupId
>
<artifactId>mongo-java-driver</artifactId> <version>2.13.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.6.2.RELEASE</version> </dependency>

配置mongodb 資料來源

  1. 資料連線地址。用一個properties儲存。
mongo.dburl=172.16.40.18:27017
mongo.dbname=qingxing
mongo.connectionsPerHost=100
mongo.threadsAllowedToBlockForConnectionMultiplier=4
mongo.maxWaitTime=1500
mongo.socketTimeout=1500
mongo.connectTimeout=1000
mongo.autoConnectRetry=true
mongo.socketKeepAlive=true
mongo.slaveOk=true
  1. 在spring 配置檔案中配置資料來源
<!-- ****************************** mongoDB begin **********************************  -->
    <!-- 一些連線屬性的設定 -->
    <mongo:mongo id="mongo" replica-set="${mongo.dburl}">
        <mongo:options connections-per-host="${mongo.connectionsPerHost}"
            threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"
            connect-timeout="${mongo.connectTimeout}" 
            max-wait-time="${mongo.maxWaitTime}"
            auto-connect-retry="${mongo.autoConnectRetry}" 
            socket-keep-alive="${mongo.socketKeepAlive}"
            socket-timeout="${mongo.socketTimeout}" 
            slave-ok="${mongo.slaveOk}"
            write-number="1" 
            write-timeout="0" 
            write-fsync="true" />
    </mongo:mongo>

    <!-- mongo的工廠,通過它來取得mongo例項,dbname為mongodb的資料庫名,沒有的話會自動建立 -->
    <mongo:db-factory dbname="${mongo.dbname}" mongo-ref="mongo" />
    <bean id="mappingContext"
        class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
    <!-- 去除集合裡的_class屬性 -->
    <bean id="defaultMongoTypeMapper"
        class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper">
        <constructor-arg name="typeKey">
            <null />
        </constructor-arg>
    </bean>
    <bean id="mappingMongoConverter"
        class="org.springframework.data.mongodb.core.convert.MappingMongoConverter">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
        <constructor-arg name="mappingContext" ref="mappingContext" />
        <property name="typeMapper" ref="defaultMongoTypeMapper" />
    </bean>
    <!-- mongodb的主要操作物件,所有對mongodb的增刪改查的操作都是通過它完成 -->
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
        <constructor-arg name="mongoConverter" ref="mappingMongoConverter" />
    </bean>


    <!-- 對映轉換器,掃描back-package目錄下的檔案,根據註釋,把它們作為mongodb的一個collection的對映 -->
    <mongo:mapping-converter base-package="com.qx.mongodb.doc" />

    <!-- mongodb bean的倉庫目錄,會自動掃描擴充套件了MongoRepository介面的介面進行注入 -->
    <mongo:repositories base-package="com.qx.mongodb.dao" />

    <!-- ***************************** mongoDB over **********************************  -->
  1. 物件的操作。建立對映關係對應。

/**
 * 教練版的語音播報
 * 
 * @author luoyang
 *
 */
@Document(collection = "mg_voice")  //存入的表名稱
public class MgVoice {

    @Id  //標誌為主鍵
    private Long cid;

    /**
     * M 男聲  F 女聲
     */
    private String voiceType;

    /**
     * 速度
     */
    private Integer voiceSpeed;

    private List<MgVoiceLibrary> voiceLibrarys;

    private List<MgVoicePlan> voicePlans;


   public Long getCid(){
      return cid;
   }
....

內嵌物件 MgVoiceLibrary


/**
 * 教練版的語音庫
 * 
 * @author luoyang
 *
 */
public class MgVoiceLibrary {

    private String lid;

    /**
     * 2 科目二 3 科目三   4 起步燈光
     */
    private Integer type;

    private String title;

    private String content;

    /**
     * 0 不是  1 是
     */
    private Integer isTemp;

    private String tempCode;

    private String tempTitle;

    private String tempContent;

    private Date updateDate;



   public String getLid(){
      return lid;
   }
   .....

增刪改查操作

在做一下的操作之前先介紹spring 中操作mongodb的類。
在之前的配置中可以看到,我們已經引入了一個類:mongoTemplate
import org.springframework.data.mongodb.core.MongoTemplate;

其中所引用的包

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.mongodb.BasicDBObject;

所以在我們的service 層 ,利用註解直接使用這個類

   @Autowired
   protected MongoTemplate mongoTemplate;
  1. 新增
 //新增很簡單,將新增的物件設定好值,直接儲存
 MgVoice mgVoice = new MgVoice();
 mgVoice.set ....//
 mongoTemplate.save(mgVoice);
  1. 修改。(修改物件的直接屬性)
 {
        "cid": 1100658, //教練ID
        "voiceType": "F",//語音型別 F女聲 M 男聲
        "voiceSpeed": 30, //語音速度
        "voiceLibrarys": [
            {
                "lid": "p2_b9dc7616-b476-40ee-8fd7-982711cece98",//語音ID
                "type": 2,//語音型別 2科目二 3科目三
                "title": "上坡起步",  //標題
                "content": "上坡起步和定點停車",//內容
                "isTemp": 1,  //是否是模板 0 不是 1 是
                "tempCode": "k2_spqb",//模板程式碼  ,也是模板圖片標題
                "tempTitle": "上坡起步",//模板標題
                "tempContent": "上坡起步和定點停車",//模板內容,供恢復預設使用
                "updateDate": "2016-04-28 00:00:00"
            },
            {
                "lid": "p3_ead65a9a-c659-4f55-a7d4-067d8935ee19",
                "type": 3,
                "title": "靠邊停車",
                "content": "請靠邊停車",
                "isTemp": 1,
                "tempCode": "k3_kbtc",
                "tempTitle": "靠邊停車",
                "tempContent": "請靠邊停車",
                "updateDate": "2016-04-28 00:00:00"
            }]
            }
我們要修改物件中的 voiceType 和 voiceSpeed  屬性
程式碼如下
   @Override
   public void updateCfg(Long cid,
                         Integer speed,
                         String type){
      Criteria criteria = Criteria.where("cid").is(cid);
      Query query = new Query(criteria);
      Update update = Update.update("voiceType", type).set("voiceSpeed", speed);
      mongoTemplate.updateFirst(query, update, MgVoice.class);
   }
  1. 修改。(物件中的 巢狀物件)
    我們要修改 voiceLibrarys 陣列 中 lid = “p2_b9dc7616-b476-40ee-8fd7-982711cece98”,的物件中的 title 和 content 屬性。使用set
   //是修改
         Query query = new Query(Criteria.where("cid").is(cid).and("voiceLibrarys.lid").is(lid));
         Update update = Update.update("voiceLibrarys.$.title", title).set("voiceLibrarys.$.content", content);
         mongoTemplate.updateFirst(query, update, MgVoice.class);

如果是要再voiceLibrarys 這個陣列中新增一個物件 使用addToset

  //語音的ID 為空是新增
         lid = getCreateId(type);
         MgVoiceLibrary voice = new MgVoiceLibrary();
         voice.setLid(lid);
         voice.setType(type);
         voice.setTitle(title);
         voice.setContent(content);
         voice.setIsTemp(0);
         voice.setUpdateDate(RDate.getCurrentDate());

         Query query = Query.query(Criteria.where("cid").is(cid));
         Update update = new Update();
         update.addToSet("voiceLibrarys", voice);
         mongoTemplate.upsert(query, update, MgVoice.class);

如果要刪除陣列voiceLibrarys 中的一個物件,物件lid=”p2_b9dc7616-b476-40ee-8fd7-982711cece98” 。 使用pull 屬性

  //刪除 語音 cid  記錄的ID  plid 陣列中的一個標記
         Query query = Query.query(Criteria.where("cid").is(cid));
         BasicDBObject s = new BasicDBObject();
         s.put("lid", plid);
         Update update = new Update();
         update.pull("voiceLibrarys", s);
         mongoTemplate.updateFirst(query, update, MgVoice.class);

除了以上的操作 還有一些屬性,例如 unset.
如果update.upset 一個數組。 就會清空物件,但是陣列大小不會變。

modifies
使用 update.modifies(key) 。 就會把這個物件裡面除了ID 以外的值全部刪除。

如果物件是這樣的。voiceLibrarys 是一個物件,不是陣列。同樣要修改title 和 content 物件。

{
        "cid": 1100658, //教練ID
        "voiceType": "F",//語音型別 F女聲 M 男聲
        "voiceSpeed": 30, //語音速度
        "voiceLibrarys": 
            {
                "lid": "p2_b9dc7616-b476-40ee-8fd7-982711cece98",//語音ID
                "type": 2,//語音型別 2科目二 3科目三
                "title": "上坡起步",  //標題
                "content": "上坡起步和定點停車",//內容
                "isTemp": 1,  //是否是模板 0 不是 1 是
                "tempCode": "k2_spqb",//模板程式碼  ,也是模板圖片標題
                "tempTitle": "上坡起步",//模板標題
                "tempContent": "上坡起步和定點停車",//模板內容,供恢復預設使用
                "updateDate": "2016-04-28 00:00:00"
            }
            }

程式碼

 //是修改
         Query query = new Query(Criteria.where("cid").is(cid));
         Update update = Update.update("voiceLibrarys.title", title).set("voiceLibrarys.content", content);
         mongoTemplate.updateFirst(query, update, MgVoice.class);

如果要刪除整條記錄。 使用remove

   @Override
   public boolean removeVoice(Long cid){
         //刪除 語音
      Query query = Query.query(Criteria.where("cid").is(cid));
      mongoTemplate.remove(query, MgVoice.class);
      return true;
   }

這裡只是簡單的介紹一些基本的操作方法。
本人只是簡單的看了一下。spring mongodb原始碼包中的程式碼。原始碼包中 也並沒有寫的很詳細。只是給了其他的文件地址。例如

/**
     * Update using the {@literal $pull} update modifier
     * 
     * @see http://docs.mongodb.org/manual/reference/operator/update/pull/
     * @param key
     * @param value
     * @return
     */
    public Update pull(String key, Object value) {
        addMultiFieldOperation("$pull", key, value);
        return this;
    }