MongoDB 操作文件 查詢文件

HuDu發表於2021-07-29

一、查詢文件

1、查詢所有

MongoDB 查詢資料的語法格式如下:
db.uesr.find() # 等同於 db.user.find({})
# 根據 name 去重
db.user.distinct("name")
find() 方法以非結構化方式來顯示所有文件。
如果你需要以易讀的方式來讀取資料,可以使用 pretry() 方法,語法格式如下:
db.user.find().pretty()
pretty() 函式以格式化的方式來顯示所有文件

注:在MongoDB中,用到方法都得用 $ 符號開頭

2、比較運算子

=!= ('$ne')> ('$gt')< ('$lt')>= ('$gte')<= ('$lte')
# 1、select * from user where id = 3
db.user.find({"id":3})

# 2、select * from user where id != 3
db.user.find({"_id":{"$ne":3}})

# 3、select * from user where id > 3
db.user.find({"_id":{"$gt":3}})

# 4、select * from user where id < 3
db.user.find({"_id":{"$lt":3}})

# 5、select * from user where id >= 3
db.user.find({"_id":{"$gte":3}})

# 6、select * from user where id <= 3
db.user.find({"_id":{"$lte":3}})

3、邏輯運算

MongoDB 中字典內用逗號分隔多個條件是 and 關係,或者直接用 $and$or$not(與或非)

# 邏輯運算:$and,$or,$ont
# 1、select * from user where id >= and id <= 4;
db.user.find({"id":{"$gte":3,"$lte":4}})

# 2、select * from user where id >= 3 and id <= 4 and age >= 4;
db.user.find({
    "_id":{"$gte":3,"$lte":4},
    "age":{"$gte":4}
})

db.user.find({
    "$and":[
        {"_id":{"$gte":3,"$lte":4}},
        {"age":{"$gte":4}}
    ]
})

# 3、select * from user where id >=0 and id <= 1 or id >=4 or name = "test"

db.user.find({
    "$or":[
        {"_id":{"$gte":0,"$lte":1}},
        {"_id":{"$lte":4}},
        {"name":"test"}
    ]
})

# 4、select * from user where id % 2 = 1;
db.user.find({"_id":{"$mod":[2,1]}})

# 5、select * from user where id % 2 != 1;
db.user.find({"_id":{"$not":{"$mod":[2,1]}}})

4、$type 操作符

MongoDB 中可以使用的型別如下表所示:

MongoDB 操作文件 查詢文件

# 查詢 name 是字串型別的資料
db.user.find({name:{$type:2}}).pretty()

5、正則

# 1、select * from user where name regexp '^z.*?(u|i)$'
# 匹配規則:z開頭、n或u結尾,不區分大小寫
db.user.find({name:/^z.*?(u|n)/i})

6、投影

MongoDB 投影意思是隻選擇必要的資料而不是選擇一整個檔案的資料。
在 MongoDB 中,當執行 find()方法,那麼它會顯示一個文件所有欄位。要限制這一點需要設定欄位列表值 10
1 用來顯示欄位而 0 用來隱藏欄位,_id 會預設顯示出來。

# 1、select name,age from user where id = 3;
db.user.find({'_id':3},{'_id':0,'name':1,'age':1})

# 2、select name,age from user where name regexp "^z.*(n|u)$";
db.user.find({
    "name":/^z.*(n|u)$/i
},
{
    "_id":0,
    "name":1,
    "age":1
}
)

7、陣列

# 查詢陣列相關
# 查詢 hobbies 中有 dancing 的人
db.user.find({
    "hobbies":"dancing"
})
# 檢視既有 dancing 愛好又有 tea 愛好的人
db.user.find({
    "hobbies":{"all":["dancing","tea"]}
})
# 檢視索引第二個愛好為 dancing 的人(索引從 0 開始計算)
db.user.find({
    "hobbies.1":"dancing"
})
# 檢視所有人的第1個到第3個愛好,第一個{}表示查詢條件為所有,第二個是顯示條件(左閉右開)
db.user.find(
    {},
    {
        _id:0,
        name:0,
        age:0
        addr:0
        hobbies:{"$slice":[0,2]}
    }
)
# 檢視所有人的最後兩個愛好,第一個{}表示查詢條件為所有,第二個是顯示條件(左閉右開)
db.user.find(
    {},
    {
        _id:0,
        name:0,
        age:0
        addr:0
        hobbies:{"$slice":-2}
    }
)
# 查詢子文件有 "country":"China"的人
db.user.find(
    {
        "addr.country":"China"
    }
)

8、排序

在 MongoDB 中使用 sort() 方法來對資料排序, sort() 方法可以通過引數指定排序的欄位,並使用 1-1 來指定排序的方式,其中 1 為升序排序,而 -1 是用於降序排序
# 按照姓名正序
db.user.find().sort({name:1})
# 按照年齡到序序,id正序
db.user.find().sort({age:-1,_id:1})

9、分頁

limit 表示取多少個 document,skip代表跳過幾個document
分頁公式:db.user.find().skip((pageNumber-1)*pageSize).limit(pageSize)
db.user.find().limit(2).skip(0) # 前兩個
db.user.find().limit(2).skip(2) # 第三個和第四個
db.user.find().limit(3).skip(4) # 第五個和第六個

10、統計

# 查詢 _id 大於 3 的人數
# 方式一
db.user.count({_id:{"$gt":3}})
# 方式二
db.user.find({_id:{"$gt":3}}).count()

二、聚合

我們在查詢時可定會用到聚合,在 MongoDB 中聚合為 aggregate,集合函式主要用到 $match $group $avg $project $concat,可以加"$match"也可以不加$match

MongoDB 操作文件 查詢文件

2.1、Aggregate與法

基本格式:db.COLLECTION_NAME.aggregate(pipeline,options)

引數說明

引數 型別 描述
pipeline array 一系列資料聚合擦耦走或階段。在版本 2.6 中更改:該方法仍然可以將流水線階段作為單獨的引數接受,而不是作為陣列中的元素;但是,如果不將管道指定為陣列,則不能指定 options 引數。目前所使用的 4.0.4 版本必須使用陣列
options document 可選。aggreate() 傳遞給聚合命令的其它選項,2.6 版本中新增功能:僅當將管道指定為陣列時才可用
2.6 中的新增功能,僅當將管道指定為陣列時才可用。
注意:使用 db.collection.aggregate() 直接查詢會提示錯誤,但是傳入一個空陣列如 db.collection.aggregate([]) 則不會報錯,且會和 find 一樣返回所有文件。

2.2、$match 和 $group

相當於 sql 語句中的 where 和 group by
{"$match":{"欄位":"條件"}},可以使用任何常用的查詢操作符 $gt,$lt,$in{"$group":{"_id":分組欄位,"新的欄位名":聚合操作符}}

# select * from db1.emp where post = "公務員"
db.emp.aggregate([{"$match":{"post":"公務員"}}])

# select * from db1.emp where id > 3 group by post;
db.emp.aggregate([
    {"$match":{_id:{"$gt":3}}},
    {"$group":{_id:"$post","avg_salary":{"$avg":"$salary"}}}
])

# select * from db1.emp where id > 3 group by post having avg(salary) > 10000;
db.emp.aggregate([
    {"$match":{_id:{"$gt":3}}},
    {"$group":{_id:"$post","avg_salary":{"$avg":"$salary"}}},
    {"$match":{"avg_salary":{"$gt":10000}}}
])

{"$group":{_id:分組欄位,"新的欄位":聚合操作符}}

將分組欄位傳給 $group 函式的 _id 欄位即可
{"$group":{_id:"$sex"}} # 按照性別分組
{"$group":{_id:"$post"}} # 按照職位分組
{"$group":{_id:{"state":"$state","city":"$city"}}} # 按照多個欄位分組,比如按照州市分組

# 分組後聚合得結果,類似於 sql 中聚合函式的聚合操作符:$sum,$avg,$max,$min,$first,$last
# select post,max(salary) from db1.emp group by post;
db.emp.aggregate([{"$group":{_id:"$post","max_salary":{"$max":"$salary"}}}])

# 取每個部門最大薪資與最低薪資
db.emp.aggregate(["$group":{_id:"$post","max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}])

# 如果欄位是排序後的,那麼 $first,$last 會很有用,比如$max 和 $min 效率高
db.emp.aggregate(["$group":{_id:"$post","first_id":{"$first":"$_id"}}}])

# 求每個部門的工資
db.emp.aggregate([{"$group":{_id:"$post","count":{"$sum":"$salary"}}},{"$sort":{"count":1}}])

# 求每個部門人數
db.emp.aggregate([{"$group":{_id:"$post","count":{"$sum":1}}},{"$sort":{"count":1}}])

# 陣列操作符
{"$addToSet":expr} # 不重複
{"$push":expr} # 重複

# 查詢崗位名以及各崗位的員工姓名:select post,group_concat(name) from db.emp group by post;
# 重複的也查詢出來
db.emp.aggregate([{"$group":{_id:"$post","names":{"$push":"$name"}}}])
# 查詢不重複的,如果有重複的保留一個
db.emp.aggregate([{"$group":{_id:"$post","names":{"$addToSet":"$name"}}}])

2.3、$project

用於投射,即設定該該鍵值對是否保留,1為保留,0位不保留,可對原有鍵值對做操作後增加自定義表示式(查詢哪些要顯示的列)
{"$project":{"要保留的欄位名":1,"要去掉的欄位名":"0","新增欄位名":" 表示式"}}

# select name,post,(age+1) as new_age from db1.emp;
db.emp.aggregate([
    {
        $project:{
            "name":1,
            "post:"1,
            "new_age":{"$add":["$age",1]}
        }
    }
])

2.4、$sort 和 $limit 和 $skip

排序:{"$sort":{"欄位名稱":1,"欄位名":-1}} #1 升序,-1 降序
限制:{"$limit":n}
跳過:{"$skip":n} # 跳過多少個文件

# 取平均工資最高的前兩個部門
db.emp.aggregate([
{
    "$group":{_id:"$post","平均工資":{"$age":"$salary"}}
},
{
    "$sort":{"平均工資":-1}
},
{
    "$limit":2
}
])

# 取平均工資最高的第二個部門
db.emp.aggregate([
{
    "$group":{_id:"$post","平均工資":{"$avg":"$salary"}}
},
{
    "$sort":{"平均工資":-1}
},
{
    "$limit":2
},
{
    "$skip":1
}
])

2.5、$sample

隨機取幾個:$sample
# 隨機獲取 3 個文件
db.emp.aggregate([
    {$sample:{size:3}}
])

2.6、$concat 和 $substr 和 $toLower 和 $toUpper

{"$substr":[$值為字串的欄位名,起始位置,擷取幾個位元組]}
# 指定的表示式或字串連線在一起返回,只支援字串拼接
{"$concat":[expr1,expr2,...,exprN]}
{"$toLower":expr} # 轉小寫
{"$toUpper":expr} # 轉大寫

# 擷取字串
db.emp.aggregate([
    {
        $project:{
            _id:0
            "str":{$substr:["$sex",0,2]}
        }
    }
])

# 拼接
db.emp.aggregate([
    {
        $project:{
            "name":1
            "post":1,
            "name_sex":{$concat:["$name","測試","$sex"]}
        }
    }
])

# 將性別的英文轉為大寫
db.emp.aggreagate([$project:{"sex":{"$toUpper":"$sex"}}])
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章