mongodb數據庫操做

安裝在Ubuntu16.04:

# 建立數據庫文件夾,這個是默認存放數據的地方,但MongoDB不會自動建立
mkdir -p /data/db
# 增長權限
chown -R $USER:$USER /data/db
wget -qO - https://www.mongodb.org/static/pgp/server-4.0.asc | sudo apt-key add -  # 導入公鑰
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list  # 爲MongoDB建立列表文件
sudo apt-get update  # 從新加載本地數據包
sudo apt-get install -y mongodb-org=4.0.12 mongodb-org-server=4.0.12 mongodb-org-shell=4.0.12 mongodb-org-mongos=4.0.12 mongodb-org-tools=4.0.12  # 安裝軟件包
echo "mongodb-org hold" | sudo dpkg --set-selections
echo "mongodb-org-server hold" | sudo dpkg --set-selections
echo "mongodb-org-shell hold" | sudo dpkg --set-selections
echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
echo "mongodb-org-tools hold" | sudo dpkg --set-selections  # 保持目前的版本,防止自動更新
# 啓動
sudo service mongodb start #或者
systemctl start mongodb

卸載

sudo apt-get purge mongodb-org*
sudo rm -r /var/log/mongodb
sudo rm -r /var/lib/mongodb

經過systemctl start mongodb 啓動時的錯誤解決

報錯以下:javascript

Failed to start mongodb.service: Unit mongodb.service not found.java

解決:正則表達式

sudo nano /etc/systemd/system/mongdb.service  # 建立服務文件
[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target

[Service]
User=mongodb
ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf
# 制定須要執行的命令的位置,                                #  制定項目運行所須要的配置文件位置
[Install]
WantedBy=multi-user.target
  • 按ctrl + x 保存退出
  • systemctl start mongodb
  • 永久有效: systemctl enable mongodb

一、文檔中值的數據類型

在mongodb中數據是以文檔的形式存在的mongodb

一、每一個文檔至關於一條記錄shell

二、多個文檔組合在一塊兒,就是集合,一個集合就至關於一張數據表數據庫

三、多個集合組合在一塊兒,就是數據庫,每一個數據庫就是一個文件夾json

  • Object ID: ⽂檔ID
  • String: 字符串, 最常⽤, 必須是有效的UTF-8
  • Boolean: 存儲⼀個布爾值, true或false
  • Integer: 整數能夠是32位或64位, 這取決於服務器
  • Double: 存儲浮點值
  • Arrays: 數組或列表, 多個值存儲到⼀個鍵
  • Object: ⽤於嵌⼊式的⽂檔, 即⼀個值爲⼀個⽂檔
  • Null: 存儲Null值
  • Timestamp: 時間戳, 表示從1970-1-1到如今的總秒數
  • Date: 存儲當前⽇期或時間的UNIX時間格式

二、Mongo shell

  • 使用mongo命令自動啓動shell,並鏈接數據庫服務器,該shell可以解析JavaScript的語法
  • 經過shell能夠完成一些列的增刪改查工做

三、文檔的基本增刪改查

  • 增長:使用insert()函數,將要插入的數據放到集合中ubuntu

    • 好比增長一個文檔,首先先建立文檔變量
post = {"title": "my first mongo"}
  • 插入文檔到blog集合中
db.blog.insert(post)
    • 批量插入:一樣適用inset方法,將你須要插入的文檔所有存放到一個數組中
    • 當咱們鏈接到服務器以後,db會自動指向正在使用的數據庫,blog爲集合名,沒有會自動建立
    • 查找:使用find()或者findOne()數組

      • find()默認顯示20條數據
    db.blog.find()
    • findOne()只顯示一條數據
    db.blog.findOne()
    • 更新:使用update()方法, 該方法接收兩個參數,第一個爲須要修改的文檔,第二個修改過的文檔

    update()方法除了接收前兩個參數外,還能夠接收另外兩個參數,而且這兩個參數都是布爾值bash

    例如:db.blog.update({"title": "My Blog Post"}, {"title": "My Blog Get"}, true, true)

    第三個參數表示upsert,可以保證操做的原子性,同時在沒有查詢到制定的集合狀況下,會以查詢條件和更新文檔爲基礎新建一個文檔,第四個參數默認是true,表示更新全部符合條件的集合,若改成false,則只更新第一個。

    • 第一:先更改文檔對象的屬性,也就是鍵值對,好比前文使用到的post變量
    給他增長一個屬性:post.comments = []
    • 找到舊文檔,替換爲新的文檔,根具給出的一個參數中的具體信息能夠找到舊文檔
    db.blog.update({"title":"my first mongo"}, post)
    • 刪除:remove(),在不給出參數的狀況下,刪除集合中的全部文檔,給出參數後,會刪除對應的文檔

      • db.blog.remove({"title":"my first mongo"})

    四、基於shell的其餘命令,利用help查看

    > help
    db.help() help on db methods
    db.mycoll.help() help on collection methods
    sh.help() sharding helpers
    rs.help() replica set helpers
    help admin administrative help
    help keys key shortcuts
    help connect connecting to a db help
    help misc misc things to know
    help mr mapreduce
    show dbs show database names
    show collections show collections in current database
    show users show users in current database
    show profile show most recent system.profile entries with time >= 1ms
    show logs show the accessible logger names
    use <db_name> set current database
    db.foo.find() list objects in collection foo
    db.foo.find( { a : 1 } ) list objects in foo where a == 1
    it result of the last line evaluated; use to further iterate
    DBQuery.shellBatchSize = x set default number of items to display on shell
    exit quit the mongo shell

    五、訪問集合

    一、當集合名與內置的函數名相同時,是沒有辦法經過db.集合名來訪問的

    二、當集合名名包含-時,好比:six-four,一樣沒有辦法經過正常的方法訪問集合,引文shell對其的解釋是兩個變量的相減

    最終的解決辦法是經過__getCollection()__來訪問,例如:db.getCollection("version"),db.getCollection("six-four")這樣才能正常訪問

    六、save shell

    save是一個shell函數,能夠在文檔不存在的時候插入,存在的時候更新,它只有一個參數,即文檔自己

    save會調用upsert,即實現文檔的自動建立和更新

    var x = db.foo.findOne()

    x.num = 12

    db.foo.save(x)

    七、修改器,以$號開頭的特殊字符串

    修改器 用法 做用
    $inc db.x.update({"a":1}, {$inc: {"b":1}}) 在原有b的基礎上加1
    $set db.x.update({"a":1}, {$set: {"b":"a"}}) 將原有b的數據修改成a,若b不存在,則建立一個
    $unset db.x.update({"a":1}, {$unset: {"b":1}}) 撤銷修改,此時的數值1,表示條件爲真的意思
    $push db.x.update({"a":1}, {$push:{"comments": {"name":"json"}}}) 該修改器只做用於數組,能夠向文檔中已有數組中添加值,固然數組不存在時,建立一個數組並添加對應內容
    $pop db.x.update({"a":1}, {$pop:{"comments": 1}}) db.x.update({"a":1}, {$pop:{"comments": -1}}) 基於數組位置的刪除,1表示從數組的尾部刪除一個元素,-1表示從數組的頭部刪除一個元素
    $addToSet db.x.update({"a":1}, {$addToSet:{"email": "aa@163.com"}) 該修改器只做用於數組,能夠向數組中添加一個值,若數組中已經有了該值,則添加失敗
    $each db.x.update({"a":1}, {$addToSet:{"email": {$each: ["1", "2", "3"]}}) 能夠遍歷出數組中的每一個值,一般與$addToSet搭配使用,完成多個值得添加,若是存在不添加
    $pull db.x.update({"a":1}, {$pull:{"email": "1"}}) 指定數組中的具體元素進行刪除,若匹配到多個值,匹配多少刪除多少
    $數組定位符 db.x.update({"comments.author": "jhon"}, {$set:{"comments.$.author": 'lili'}}) 定位符只匹配第一個匹配到的文檔

    八、查詢

    8.一、指定鍵返回查詢

    • 查詢使用find函數或者findOne函數
    • 查詢返回指定字段,也就是查詢指定鍵
    • db.blog.find({"a":2}, {"ss":1, "wo": 0}),當匹配到包含{"a":2}的文檔後,只返回"_id" 和"ss"兩個鍵,"_id"是默認返回的,其中1表示真,0表示假

    8.二、條件查詢

    命令 用法 做用
    $gt db.users.find({"age": {"$gt": 20}}) 查詢users集合中年齡大於20的文檔
    $gte db.users.find({"age": {"$gte": 20}}) 查詢users集合中年齡大於等於20的文檔
    $lt db.users.find({"age": {"$lt": 20}}) 查詢users集合中年齡小於20的文檔
    $lte db.users.find({"age": {"$lte": 20}}) 查詢users集合中年齡小於等於20的文檔
    $ne db.users.find({"username": {"$ne": "andy"}}) 查詢users集合中用戶名不等於andy的文檔
    $or db.users.find({"$or": [{"age": 20},{"username": "andy"} ]}) $or 鍵對應的值是一個數組,知足數組中任何一個條件的文檔都會被查找出來,可做用於不一樣的鍵
    $in db.users.find({"age": {"$in": [12 ,10, 22]}}) $in鍵對應的值是一個數組,知足數組中任何一個條件的文檔都會被查找出來,可是它只做用於同一個鍵
    $nin db.users.find({"age": {"$nin": [12 ,10, 22]}}) $nin鍵對應的值是一個數組,不知足數組中任何一個條件的文檔都會被查找出來,它也只做用於同一個鍵
    $mod db.users.find({"age": {"$mod": [5, 1]}}) $mod表示取模運算,運算完成後在做爲查詢條件,它對應的值是一個數組,該數組只有兩個值且有順序,第一個表示除數,第二個表示餘數,在這裏表達的意思是,找出年齡除以5後餘數爲1的文檔
    $not db.users.find({"$not":{"age": {"$mod": [5, 1]}}}) $not是元條件查詢,即做用其餘條件查詢之上,例如他與$mod取模運算結合使用,表示取非
    $existe db.users.find({"x":{"$existe": true}}) $existe判斷該鍵是否真實存在,存在則顯示出來
    /joy/i db.users.find({"username": /joy/i}) 這裏是利用正則表達式去匹配所查詢文檔的某個鍵對應的值,i表示不區分大小寫

    $where 自定義查詢

    db.stu.find({
        $where:function() {
            return this.age>30;}  // this 表明當前查詢的文檔,找出年齡大於30歲的文檔
    })

    8.三、數組查詢

    8.3.一、$all
    • 建立以下集合並加入三條文檔:

    db.fruit.insert({"_id": 1, "fruits": ["banana", "peach", "apple"]})

    db.fruit.insert({"_id": 2, "fruits": ["orange", "kumquat", "apple"]})

    db.fruit.insert({"_id": 3, "fruits": ["banana", "cherry", "apple"]})

    • {"$all": ["banana", "apple"]},做用於數組,

    使用db.fruit.find({"fruits": {"$all" : ["banana", "apple"]}}),執行結果是數值fruits中只要包含有"banana"和"apple"元素的文檔,所有返回,忽略數組中元素的順序

    • 特殊用法

    {"fruits": {"$all" : ["banana"]}}和{"fruits":"banana"},這兩條查詢效果是同樣的

    • 基於數組下標的查找

    好比:db.fruit.find({"fruits.2":"apple"}),只要數組中指定位置的元素匹配正確,就會返回結果

    8.3.二、$size
    • 查詢固定數組長度的文檔

      • 用法:db.fruit.find({"fruits": {"$size": 3}})
      • 不能配合其餘條件命令使用,例如$gt,而實際生產中,老是須要咱們去查找數組範圍的文檔
    • 在文檔中建立一個size的字段來專門描述數組的長度,變相的經過size的值來範圍查找

      • 例如上文:增長一個size字段,db.fruit.update({"_id": 1}, {"$inc": {"size": 3}})
      • 增長數組的內容時,同時增長size的值
    db.fruit.update({"_id": 1}, {"$push" : {"fruits": "pear"}, "$inc" : {"size": 1}})
    • 最後就能夠進行範圍查找了
    db.fruit.find({"size": {"$gt": 3}})
    8.3.三、$slice
    • 對查找到的數組進行切片處理,並返回新的切片後的文檔

      • 使用$slice必須配合find函數的第二個參數使用,find的第二參數是指定文檔中的鍵返回的,未說起或者對應值爲0,將不會被返回,當使用$slice後,即便不說起文檔中的其餘鍵一樣會返回
    db.fruit.find({"_id" : 1}, {"fruits": 1})
    >{ "_id" : 1, "fruits" : [ "banana", "peach", "apple", "pear"]}  # 這裏_id默認返回
    # 若是將_id的值變爲0,則不會被返回
    db.fruit.find({"_id" : 1}, {"fruits": 1, "_id": 0})  # 數字表明真假
    >{"fruits" : [ "banana", "peach", "apple", "pear"]}
    # 當對返回的鍵使用切片後$slice,文檔中全部的鍵默認都會返回
    db.fruit.find({"_id": 1}, {"fruit": {"$slice": 3}})
    >{ "_id" : 1, "fruits" : [ "banana", "peach", "apple" ], "size" : 4 }
    • 對數組正向切割

    db.fruit.find({"_id": 1}, {"fruit": {"$slice": 3}}), $slcie對應的值是正數便可,獲得數組的前三個元素

    • 對數組反向切割

    db.fruit.find({"_id": 1}, {"fruit": {"$slice": -3}}), $slcie對應的值是負數便可,獲得數組的後三個元素

    • 對數組指定範圍切片

    db.fruit.find({"_id": 1}, {"fruit": {"$slice": [1, 3]}}),$slice對應的值爲數組,該數組表示你要操做的數組下標

    ,獲得結果:{ "_id" : 1, "fruits" : [ "peach", "apple", "pear" ], "size" : 4 },包含起始和結束下標

    8.四、查詢內嵌文檔

    • 在mongodb中文檔的表現形式,像極了javascript中的對象,因此能夠經過對象.屬性的方法,來訪問MongoDB中的內嵌文檔,但也能夠匹配整個內嵌文檔
    • 方法一:若有文檔

    {"name": {"first": "Joe", "last": "Schmoe"}, "age": 27},在集合people中

    db.people.find({"name": {"first": "Joe", "last": "Schmoe"}}),這裏能夠找到有這個內嵌文檔的文檔,可是有一個缺點,就是查詢條件必須匹配整個內嵌文檔,不然就會匹配失敗,同時順序也不可以錯,也就是要求精確匹配

    • 方法二:經過對象.屬性的方法來訪問,就不存在限制了

    db.people.find({"name.first": "Joe", "name.last": "Schmoe"}),這裏就要求精確匹配了

    • $elemMatch

    將限定條件進行分組,僅當須要對一個內嵌文檔的多個鍵操做時纔會用到

    db.blog.find({"comments": {"$elemMatch": {"author": "joe", "score": {"$gte": 5}}}})

    九、排序、分頁和跳過

    9.一、排序sort

    • 使用方法:db.collection.find().sort({"username": 1})
    • 返回結果按升序排列,同時能夠設置多個鍵排序

    db.collection.find().sort({"username":1, "age": -1})

    先以username升序排列,若username相同,則按照age降序排列

    9.二、分頁limit

    • 使用方法:

    db.collection.find().limit(20),表示每頁返回20條數據

    9.三、跳過skip

    • db.collection.find().skip(20),跳過前20個數據

    組合實現分頁查詢

    • db.collection.find().limit(20).sort({"age": -1})

    按照年齡從大到小取出前二十條文檔

    • db.collection.find().limit(20).skip(20).sort({"age": -1})

    跳過前20條,取後20條的結果

    十、建立索引

    • 方法:db.users.ensureindex({"username": 1})

    十一、遊標對象

    使用find函數返回的對象能夠賦值給一個變量,這個變量就能夠理解爲是一個遊標對象

    遊標對象屬性 :可迭代(iterable)

    遊標對象方法 :hasNext()判斷是否還有下一條數據

    next()獲取下一條數據

    十二、聚合函數(aggregate)

    12.一、count函數

    db.stu.count() # 返回fruit集合中的總文檔數

    現有以下集合mycol:

    { "_id" : 1, "name" : "tom", "sex" : "男", "score" : 100, "age" : 34 }
    { "_id" : 2, "name" : "jeke", "sex" : "男", "score" : 90, "age" : 24 }
    { "_id" : 3, "name" : "kite", "sex" : "女", "score" : 40, "age" : 36 }
    { "_id" : 4, "name" : "herry", "sex" : "男", "score" : 90, "age" : 56 }
    { "_id" : 5, "name" : "marry", "sex" : "女", "score" : 70, "age" : 18 }
    { "_id" : 6, "name" : "john", "sex" : "男", "score" : 100, "age" : 31 }

    12.二、$group,$sum

    db.stu.aggregate({$group:{_id: "$sex", Count: {"$sum": 1}}})

    12.三、$group,$push

    db.stu.aggregate(
         {$group:
             {
                _id:"$gender",
                 name:{$push:"$name"}
             }
         }
    )  把全部的數據放到一塊兒
    $$ROOT, 把整個文檔放到一個數組中
    db.stu.aggregate(
         {$group:
             {
                 _id:null,
                 name:{$push:"$$ROOT"}
             }
         }
    )

    12.四、$match`

    db.stu.aggregate(
         {$match:{age:{$gt:20}}
         )

    12.五、$project

    db.stu.aggregate(
         {$project:{_id:0,name:1,age:1}}
         ) //控制顯示的文檔鍵

    12.六、$sort

    db.stu.aggregate(
         {$group:{_id:"$gender",counter:{$sum:1}}},
         {$sort:{counter:-1}}
    )

    12.七、$limit,$skip

    db.stu.aggregate(
         {$group:{_id:"$gender",counter:{$sum:1}}},
         {$sort:{counter:-1}},
         {$skip:1},
         {$limit:1}
    )

    1三、數據庫命令(runCommand)

    13.一、distinct函數

    db.runCommand({"distinct": "fruit" , "key": "fruits"})

    runCommand指令表示運行命令,括號內的參數的第一個鍵爲具體的指令,指令所對應的的值是要操做的集合,key對應的是要操做的鍵。

    distinct所表達的意思是找出集合中某個鍵對應多少不一樣的值,也就是去重。

    13.二、group函數

    • 對文檔進行分組,stocks集合中有如下文檔:

    db.stock.insert({"day" : "2010/10/03", "time": "10/03/2010 03:57:01 GMT-400", "price": "4.23"})

    db.stock.insert({"day" : "2010/10/04", "time": "10/04/2010 11:28:39 GMT-400", "price": "4.27"})

    db.stock.insert({"day" : "2010/10/03", "time": "10/03/2010 05:00:22 GMT-400", "price": "4.10"})

    db.stock.insert({"day" : "2010/10/06", "time": "10/06/2010 05:27:58 GMT-400", "price": "4.30"})

    db.stock.insert({"day" : "2010/10/04", "time": "10/04/2010 08:34:50 GMT-400", "price": "4.01"})

    獲取到天天最新的股票交易價格

    • 使用數據庫命令的模式來執行group命令:
    db.runCommand({"group":{
        "ns": "stock",
        "key": {"day": true},  // 程序執行到這裏以後,就已經對集合分組完畢了
        "$keyf": function(X){
            return X.toLowerCase() // 將須要排序的鍵進行轉換,好比進行大小寫轉換
        },
        "initial":{"time":0},  // 每組文檔遍歷時候的初始值
        "$reduce":function(doc, prev){
            if(doc.time>prev.time){  // 判斷時間大小,更新要顯示的最近時間
                prev.time = doc.time;
                prev.price= doc.price;
            }
        },
        "condition": {"day": {"$gt": "2010/10/03"}},// 對分組進行條件限制,必須大於條件時間
        "finalize":function(prev){  //對返回結果作最後的修改,和限定
            ...
        }
    }})

    參數解析

    group:對集合執行的操做,即分組

    ns:須要操做的數據集

    key:以文檔中的哪一個鍵進行分組

    $keyf: 對須要分組的鍵進行條件轉換

    initial: 每組文檔的初始化值,也就是最終分完組後顯示的字段的初始化值

    $reduce: 對分組後的顯示文檔作最後的操做,在上述案例中,就是找到那一組文檔中時間最新的文檔,而後把他的時間和股票交易價格顯示到咱們能夠看到的結果

    condition: 對分組進行條件限制

    finalize: 對返回的結果作最後的修改

    #### 13.三、findAndModify

    db.runCommand({"findAndModify": "stock", # 操做集合stock

    ​ "query": {"day":{"$gt": "2010/09/30"}}, # 查詢條件

    ​ "sort": {"day": -1}, # 排序鍵

    ​ "remove": true # 是否刪除文檔true

    })

    #### 13.四、建立固定大小的集合

    db.creatCollection("my_collection",{"capped": true, "size": 100000})

    參數解析

    my_collection:集合名

    capped:表示是否限值集合的大小,true表示限值,false表示不限制

    size:表示集合大小,這裏表示100000個字節

    更多技術資訊可關注:gzitcast

    相關文章
    相關標籤/搜索