Mongodb Shell 速查

Mongodb 指令快速查詢,實用筆記

CURD、index

Insert
db.myCol.insertOne(JsonObj)
db.myCol.insertMany([ JsonObj1, JsonObj2,... ])
db.myCol.insert() //One or Many 都可用
Update
db.myCol.updateOne(filter, update, options)
db.myCol.updateMany(filter, update, options)
db.myCol.update()
//新增or更新欄位 (也可用 aggregate $addFields)
db.myCol.update(filter, {$set:{field:'value'}});
db.myCol.replaceOne(filter, replacement, options)
db.myCol.findOneAndUpdate()
db.myCol.findOneAndReplace()
db.myCol.findAndModify()
write concern:寫入等級設定 (link)

  • w:-1 (嚴謹性:非常低);發生資料庫寫入錯誤一慮不回傳
  • w:0 (嚴謹性:低);只可以偵測到網路錯誤
  • w:1 (嚴謹性:中, default)
  • w:1,j:1 (嚴謹性:高);在寫入日誌後才回傳處理過程
  • w:2 (嚴謹性:高 );這個級別只在replica set的部署模式下生效
  • w為設定寫入等級 ; j為日誌設定

Delete
db.collection.deleteOne()
db.collection.deleteMany()
db.collection.remove()
db.collection.findOneAndDelete()
Index操作
db.collection.createIndex()
db.collection.getIndexes() 
db.collection.dropIndex()
db.collection.dropIndexes()
db.collection.ensureIndex()
Cursor
db.col.find().forEach( function(d) { print(d.name );});

Sql vs Mongo 對應語法(link)


簡易的查詢使用 db.collection.find(query,指定欄位)
  • select a,b,c
  • db.myCol.find({},
        { column1:1, column2:1, _id:0 } //_id預設都會撈出,給予 0 部顯示
    )
    
  • equal/not equal
  • db.myCol.find({col1: "abc" }) //equal
    db.myCol.find({col1: {$ne: "abc"} }) //not equal
    db.myCol.find({col1: {$in:["A","D"]} }) //where in
    db.myCol.find({col1: {$nin:["B","C"]} }) //where not in
    
  • like
  • 只需改關鍵字寫法,就是 like,差異是不用加 ""
    注意:若要在陣列中與其他參數使用,須完整寫成 $regex: //
    db.myCol.find({col1: /bc/ }) //like %bc%
    db.myCol.find({col1: /^bc/ }) //like bc%
    db.myCol.find({col1: /bc$/ }) //like %bc (結尾為 bc 者)
    
    db.myCol.find({col1: {$not: "abc"} }) //not like
    db.myCol.find({col1: {$in:[ /bc/ , /def/ ]} }) //where in
    db.myCol.find({col1: {$in:[ /def/ , "abc" ]} }) //where in equal+like, array
    
    db.myCol.find({col1: {$nin:[ /ab/ , /cde/ ]} }) //where not in
    
  • and
  • db.myCol.find({col1: "A", col2: 20 }) //2 columns
    db.myCol.find({col1: {$regex: /bc/, $not:""} }) //same column
    
    db.myCol.find({$and: [ query表達式1 , query表達式2 ]}) //2 columns in collection
    //not union
    
  • or
  • 依序遇到寶達式為 true 就停止,詳細行為請見(link)
    db.myCol.find({ $or: [ 
        { query表達式1 },
        { query表達式2 }, ...
    })
    
    db.myCol.find({
        $and: [
            {$or : [{'a':1},{'b':2}]},
            {$or : [{'a':2},{'b':3}]}
        ] 
    }) //multi or or
    
  • not empty/exists
  • db.myCol.find({col1: {$exists:true} }) //exists
    db.myCol.find({col1: {$not: ""} }) //not empty
    
    db.myCol.find({pic1: {$exists:true, $not:{$size:0}} }) //file exist
    db.myCol.find({arr1: {$size: 0} }) //empty array
    
  • <>=
  • db.myCol.find({ age:{$gt:20} }) //greate then
    db.myCol.find({ age:{$gt:20, $lt:50} }) //greate then + less then
    
    db.myCol.find({ age:{$gte:20} }) //greate then + equal
    db.myCol.find({ age:{$lte:50} }) //less   then + equal
    
  • orderby / limit / skip
  • db.myCol.find().sort( { col1: 1, col2:-1 } ) //1=ASC, -1=DESC
    db.myCol.find().skip(10).limit(5) // limit 10,5
    
  • count()
  • db.myCol.count() //count(*)
    db.myCol.find({col1: "abc"}).count() //count(col1)
    db.myCol.count({col1: "abc"}) //count(col1),寫法2
    
    //先 groupby 再 count,請用下方 Aggregate
    
  • union()
  • Explain SQL
  • 建 index
  • hint()
  • $rename 改欄位名稱
  • db.getCollection("myTable").update({}, {$rename:{"oldName":"newName"}}, false, true)
    
  • $unset 刪除欄位
  • db.getCollection('myTable').update({}, { $unset: { columnName: "" } }, { multi: true })
    
  • full rext search 全文檢索
    • $search

Aggregate

強大的 query method
  • groupby count
  • db.myCol.aggregate([
        {$group : {_id : "$欄位名稱", total : {$sum : 1}}}
    ])
    
  • date range
  • db.myCol.aggregate([
        { $match: { "日期欄位名稱": { $gte: ISODate("2017-05-04 10:53:43.059Z"), $lt: ISODate("2017-05-09 10:53:53.059Z") } } }
    ])
    
    • 若要與 $group 合併使用,須放在前面
    • PHP下,時間使用 new MongoDate(time()) 來轉換,MongoDate 吃 timestamp、並轉成 UTC
  • Join by column + groupby count
  • 子查詢、orderby limit + orderby

基礎method

  • $project
  • db.myCol.aggregate([
        { $project: { 
            mycol1: 1, //顯示欄位
            mycol2: 0, //不顯示欄位(似乎不能1一起用)
            "nn": "123" //動態新增欄位
        }}
    ]);
    
  • $lookup JOIN by column
  • db.myCol.aggregate([
      { $lookup: {
        "from": 要join的table,
        "localField": 自己的欄位,
        "foreignField": 對方的欄位,
        "as": JOIN結果陣列的名稱
      }},
    ]);
    
  • $addFields 動態新增欄位
  • db.myCol.aggregate([
        { "$addFields": { 
            "nn": "123"
        }}
    ]);
    
  • $size 計算某Array內數量
  • "newCol": { $size: "$要計算的欄位" }
    
  • $match
  • $filter 用條件過濾子查詢(array)
  • $group
  • $setUnion 合併陣列
  • $out 將結果輸出(新增)成新 collection
  • $geoNear
  • $unwind 陣列拆成 rows
  • $sample
  • $sort
  • $skip 略過筆數(分頁用)
    • aggregate 不能用 modifier 寫法
  • $limit 取幾筆($skip要先使用)
  • $redact
  • 字串處理(完整文件)
    • $concat 合併文字
    • mycol1 : { $concat: [ "$col2", " - ", "$col3" ] } 
      
    • $substr 剪裁文字
db.myCol.aggregate([
  { "$match": { "rating": "important" } },
  { "$sort": { "date": -1 } },
  { "$limit": 20 },
  { "$lookup": {
    "from": "user",
    "localField": "user_id",
    "foreignField": "_id",
    "as": "userinfo"
  } },
  { "$unwind": "$userinfo" },
  { "$project": {
    "text": 1,
    "date": 1,
    "userinfo.name": 1,
    "userinfo.country": 1
  } }
]);

Map-Reduce

在集合 orders 中查找 status:"A" 的資料,並根據 cust_id 來分組,並計算 amount 的總和。


GridFS

file list

mongofiles -d 資料庫 list -u 帳號 -p 密碼 --authenticationDatabase admin
get / delete / put file
mongofiles -d 資料庫 list -u 帳號 -p 密碼 --authenticationDatabase admin 方法 檔名.副檔名
search file
mongofiles -d 資料庫 list -u 帳號 -p 密碼 --authenticationDatabase admin search 字串
連續匯出
#!/bin/bash

while read -r line; do
    file=$(echo "$line" | awk -F'\t' '{ print $1 }')
    [[ $file == 'connected to'* ]] && continue
    mongofiles -d 資料庫 list -u 帳號 -p 密碼 --authenticationDatabase admin get "$file"
done < <(mongofiles list -d 資料庫 list -u 帳號 -p 密碼 --authenticationDatabase admin)


Explain

mongo shell - eval(link)

有時候需要寫自動化 shell script,就會派上用場
#!/bin/bash

#刪除 db
mongo "localhost:27017/mydb" -u 帳號 -p 密碼 --authenticationDatabase admin --eval "printjson(db.dropDatabase())"

狀況

  • exceeds maximum document size code 4568
    • 超過 1個 document 16MB

備援

  • db1.collection 複製到 db2.collection
  • MONGO> use db1;
    MONGO> db.myCol.find().forEach(function(d){ db.getSiblingDB('db2')['myCol'].insert(d); });
  • 匯出
  • 匯入
  • 跨 host 複製 collection
  • $ rm -f /tmp/copy_collection.json
    $ mongoexport --ssl --host fromhost.com -d mydb -u myuser -p mypw --authenticationDatabase admin --collection $fromCollection --out /tmp/copy_collection.json
    $ mongoimport --ssl --host tohost.com -d mydb -u myuser -p mypw --authenticationDatabase admin --collection $toCollection --file /tmp/copy_collection.json

產出

  • 產出 json (pretty)
  • $ mongoexport --ssl --host abc.com -d mydb -u myuser -p mypw --authenticationDatabase admin --collection mycollection --out abc.json --jsonArray  --pretty
    #用col1遞增排序 --sort "{col1: 1}"
    

權限

    Role 總覽 (link)
  • 建立 SuperUser
  • > use admin
    > db.createUser( { user: "root", pwd: "root", roles: [ { role: "root", db: "admin" } ] } )
    
    daemon 啟用權限驗證
    $ sudo -s
    $ service mongod stop
      #或者 mongod --config /etc/mongod.conf --shutdown
    $ rm /var/lib/mongodb/mongod.lock
    $ nano /etc/mongod.conf
       #加上
       security:
         authorization: enabled
    $ service mongod start
      #若沒正常啟動,請查詢 tail /var/log/mongodb/mongod.log
    $ mongo
      #權限若有生效, show dbs 會出現 "not authorized" 訊息
    $ shutdown -r now 看看是否正常運作
    
  • 建立 DB owner
  • *.須先啟用 admin
    > use mydb
    > db.createUser( { user: "user", pwd: "password", roles: [ { role: "dbOwner", db: "mydb" } ] } )
    
  • 登入
  • $ mongo -u user -p password --authenticationDatabase admin
    #或
    $ mongo
    > use admin
    > db.auth('user','password'); 
    
  • URI 寫法
  • mongodb://user:password@localhost:27017/collection?authSource=admin

實用指令

每筆資料,複製指定欄位
db.getCollection(table).find().forEach(function(d){        
    db.getCollection(table).update(
        {id: d._id},
        {$set: {
            newcol: d.email
        }}
    );
});
每筆資料,某欄位全部小寫
db.getCollection(table).find().forEach(function(d){       
    if(d.email) d.email = d.email.toLowerCase(); 
    db.getCollection(table).update(
        {id: d._id},
        {$set: {
            email: d.email
        }}
    );
});

常見狀況

  • Server啟動時,mongod 沒起來
  • Ubuntu 16.04 改用 systemd 後,mongod service 需手動去啟用
    #執行一次
    $ sudo systemctl enable mongod.service
    $ sudo systemctl daemon-reload
    
    若沒 run 起來,可能是 service file 不存在,則須自行撰寫 (參考這篇)
    急的話,可先使用 /usr/bin/mongod --quiet --config /etc/mongod.conf &
  • Failed: error connecting to db server: no reachable servers
  • 執行 mongo 會正常,但其他 tool 會出錯,不要使用 ubuntu apt 原本的 mongodb
    改成用官方建議的安裝方式 (link)
  • Error: couldn't connect to server 127.0.0.1:27017, connection attempt failed :
    /mongo/shell/mongo.js:251:13
  • 檢查  log,若是連線 lock 住
    $ sudo rm /var/lib/mongodb/mongod.lock
    $ sudo mongod --repair
    $ sudo service mongod start
    

延伸閱讀

  • MongoDB的使用中的一些問題 (link)
  • MongoDB Schema 設計指南 (link)
  • CAP & BASE 理論看 MongoDB (link)
  • 30天之你好MongoDB(link)
  • SQL 到彙總(Aggregation)對應表(link)
Mongodb Shell 速查 Mongodb Shell 速查 Reviewed by Wild on 1/05/2018 12:51:00 下午 Rating: 5

沒有留言:

沒有Google帳號也可發表意見唷!

技術提供:Blogger.