mongo-03-查詢文件
技術標籤:005-mongo實戰mongodb
1. find 讀取文件
db.<collection>.find(<query>,<projection>)
- query : 定義了讀取操作時篩選文件的條件
- projection : 定義了對讀取結果進行的投射,也就是隻返回某些欄位
1.1 讀取文件
不進行篩選和投射
> db.user.find() { "_id" : "1", "money" : 1000, "name" : "劉一" } { "_id" : "2", "money" : 1000, "name" : "陳二" } { "_id" : "3", "money" : 1000, "name" : "張三" } { "_id" : "4", "money" : 1000, "name" : "李四" } { "_id" : "5", "money" : 1000, "name" : "王五" } { "_id" : "6", "money" : 1000, "name" : "趙六" } { "_id" : "7", "money" : 1000, "name" : "孫七" } { "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" } { "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" } >
查詢 name 為 張三的文件
> db.user.find({"name":"張三"})
{ "_id" : "3", "money" : 1000, "name" : "張三" }
>
1.2 pretty 格式化顯示文件
> db.user.find().pretty() { "_id" : "1", "money" : 1000, "name" : "劉一" } { "_id" : "2", "money" : 1000, "name" : "陳二" } { "_id" : "3", "money" : 1000, "name" : "張三" } { "_id" : "4", "money" : 1000, "name" : "李四" } { "_id" : "5", "money" : 1000, "name" : "王五" } { "_id" : "6", "money" : 1000, "name" : "趙六" } { "_id" : "7", "money" : 1000, "name" : "孫七" } { "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" } { "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" } >
1.3 篩選文件:比較操作符
{<field>:{$<operator>:<value>}}
比較操作符 $<operator>
:
- $eq : 匹配欄位值相等的文件
- $ne : 匹配欄位值不相等的文件
- $gt : 匹配欄位值大於查詢值的文件
- $gte : 匹配欄位值大於或等於查詢值的文件
- $lt : 匹配欄位值小於查詢值的文件
- $lte : 匹配欄位值小於或等於查詢值的文件
- KaTeX parse error: Expected '}', got 'EOF' at end of input: …文件 `{<field>:{in:[,…]}}`
- KaTeX parse error: Expected '}', got 'EOF' at end of input: …文件 `{<field>:{
查詢 money 等於 1000的文件,和查詢 money 大於 1000的文件
# 查詢 money 等於 1000的文件
> db.user.find({"money":{$eq: 1000}})
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
{ "_id" : "7", "money" : 1000, "name" : "孫七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" }
# 查詢 money 大於 1000的文件
> db.user.find({"money":{$gt: 1000}})
>
查詢 name 為 張三或者趙六的文件
> db.user.find({"name":{$in: ["張三","趙六"]}})
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
>
1.3 篩選文件:邏輯操作符
邏輯操作符 $<operator>
:
- $not 匹配篩選條件不成立的文件
- $and 匹配多個篩選條件全部成立的文件
- $or 匹配至少一個篩選條件成立的文件
- $nor 匹配多個篩選條件全部不成立的文件
1.3.1 $and 匹配多個篩選條件全部成立的文件
{$and: [{<expression1>},{<expression2>},...,{<expressionN>}]}
查詢 money<2000 , name = 張三 的文件
> db.user.find({$and: [{"money":{$lt:2000}},{"name":"張三"}]})
{ "_id" : "3", "money" : 1000, "name" : "張三" }
>
欄位名可以用雙引號引起來,也可以不用雙引號。
當篩選條件應用在不同的欄位上時,可以省略 $and 操作符
查詢 money<2000 , name = 張三 的文件,省略 $and
> db.user.find({money:{$lt:2000},name:"張三"})
{ "_id" : "3", "money" : 1000, "name" : "張三" }
>
當篩選條件應用在同一個欄位上時,也可以簡化命令
查詢 money > 500 且 money < 2000 的文件
> db.user.find({money:{$gt:500, $lt:2000}})
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
{ "_id" : "7", "money" : 1000, "name" : "孫七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" }
>
1.3.2 $or 匹配至少一個篩選條件成立的文件
{$or: [{<expression1>},{<expression2>},...,{<expressionN>}]}
查詢 name 為 張三 或者 李四 的文件
> db.user.find({$or: [{"name":"張三"},{"name":"李四"}]})
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
>
上面的操作等同於
> db.user.find({name:{$in:["張三","李四"]}})
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
>
1.3.3 $nor 匹配多個篩選條件全部不成立的文件
{$nor: [{<expression1>},{<expression2>},...,{<expressionN>}]}
查詢 name 不為 張三 和 李四 的文件
> db.user.find({$nor: [{"name":"張三"},{"name":"李四"}]})
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
{ "_id" : "7", "money" : 1000, "name" : "孫七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" }
>
1.4 欄位操作符
1.4.1 $exists 匹配包含查詢欄位的文件
{field: {$exists: <boolean>}}
查詢包含 name 欄位的文件
> db.user.find({name: {$exists: true}})
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
{ "_id" : "7", "money" : 1000, "name" : "孫七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" }
查詢包含 phone 欄位的文件
> db.user.find({phone: {$exists: true}})
>
1.4.2 $type 匹配欄位型別符合查詢值的文件
查詢 _id 為 string 型別的文件
> db.user.find({_id: {$type: "string"}})
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
{ "_id" : "7", "money" : 1000, "name" : "孫七" }
>
查詢 _id 不為 string 型別的文件
> db.user.find({_id: {$not:{$type: "string"}}})
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" }
>
1.5 陣列操作
1.5.1 $all 匹配陣列欄位中包含所有查詢值的文件
{field: {$all: [<value1>,<value2>,..,<valueN>]}}
插入一條包含陣列欄位 addr 的文件,並進行 $all 匹配
# 插入一條包含陣列欄位 addr 的文件
> db.user.insert({"money":3000,"name":"廣東人", addr: ["廣州","深圳"]})
WriteResult({ "nInserted" : 1 })
# 匹配 addr 欄位中包含 "廣州","深圳" 的 文件
> db.user.find({addr: {$all:["廣州","深圳"]}})
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "廣東人", "addr" : [ "廣州", "深圳" ] }
# 匹配 addr 欄位中包含 "廣州" 的 文件
> db.user.find({addr: {$all:["廣州"]}})
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "廣東人", "addr" : [ "廣州", "深圳" ] }
# 匹配 addr 欄位中包含 "廣州","北京" 的 文件
> db.user.find({addr: {$all:["廣州","北京"]}})
>
1.5.2 $elemMatch 匹配陣列欄位中至少存在一個值滿足篩選條件的文件
{field: {$elemMatch: [<query1>,<query2>,..,<queryN>]}}
查詢 addr 陣列欄位的任意一個item 匹配是 “廣州”的文件
> db.user.find({addr: {$elemMatch: {$eq: "廣州"}}})
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "廣東人", "addr" : [ "廣州", "深圳" ] }
>
1.6 正則匹配
{field: {$regex:/pattern/, $options: "options"}}
資料準備
> db.user.insert({"money":2000,"name":"zhangsan", addr: ["廣州","北京"]})
WriteResult({ "nInserted" : 1 })
> db.user.insert({"money":2000,"name":"ZHANG", addr: ["三亞","北京"]})
WriteResult({ "nInserted" : 1 })
> db.user.find()
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
{ "_id" : "7", "money" : 1000, "name" : "孫七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" }
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "廣東人", "addr" : [ "廣州", "深圳" ] }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "廣州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亞", "北京" ] }
>
查詢 name 以 zhang 開頭的文件
> db.user.find({name: {$regex: /^zhang/}})
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "廣州", "北京" ] }
>
查詢 name 以 zhang 開頭的文件,並忽略大小寫
> db.user.find({name: {$regex: /^zhang/, $options: "i"}})
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "廣州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亞", "北京" ] }
>
2. 文件遊標
db.collection.find()
返回一個文件集合遊標(cursor)。
遊標常用函式有:
- cursor.limit()
- cursor.skip()
- cursor.count()
- cursor.sort()
2.1 cursor.limit(<number>) 限制返回結果的最大數量
只返回前3條記錄
> db.user.find().limit(3)
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
>
limit(0) 不做數量限制,返回所有
> db.user.find().limit(0)
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
{ "_id" : "7", "money" : 1000, "name" : "孫七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" }
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "廣東人", "addr" : [ "廣州", "深圳" ] }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "廣州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亞", "北京" ] }
>
2.2 cursor.skip(<offset>) 跳過前面幾條記錄
跳過前3條記錄
> db.user.find().skip(3)
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
{ "_id" : "7", "money" : 1000, "name" : "孫七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" }
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "廣東人", "addr" : [ "廣州", "深圳" ] }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "廣州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亞", "北京" ] }
>
2.3 cursor.count(<applySkipLimit>) 統計數量
預設情況下,<applySkipLimit>為false,即 cursor.count() 不會考慮 cursor.skip() 和 cursor.limit() 的效果
預設情況下,<applySkipLimit>為false
limit(3),檢視 <applySkipLimit>為false和true,count() 的結果
# 預設情況下,applySkipLimit = false
> db.user.find().limit(3).count()
12
# applySkipLimit = true
> db.user.find().limit(3).count(true)
3
# applySkipLimit = false
> db.user.find().limit(3).count(false)
12
>
在不提供篩選條件時,cursor.count() 會從集合的元資料 Metadata中取得結果。
當資料庫分散式結構較為複雜時,元資料中的文件數量可能不準確,在這種情況下,應該避免應用不提供篩選條件的 cursor.count() 函式,而是用聚合管道來計算文件數量。
2.4 cursor.sort() 排序
cursor.sort(<document>)
這裡的 <document> 定義了排序的要求
{field: ordering}
- 1 : 表示由小到大的正向排序
- -1 : 表示逆向排序
按照 money 逆向排序從大到小,name 按字母正向排序的方式排列
> db.user.find().sort({money: -1,name: 1})
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "廣東人", "addr" : [ "廣州", "深圳" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亞", "北京" ] }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "廣州", "北京" ] }
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吳九" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : "7", "money" : 1000, "name" : "孫七" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "趙六" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
>
2.5 cursor.sort()、cursor.skip()、cursor.limit()執行順序
cursor.skip()在cursor.limit()之前執行
無論如何調換 skip() 和 limit() 的順序,都是先執行 skip,再執行 limit
> db.user.find().limit(3).skip(1)
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
> db.user.find().skip(1).limit(3)
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
{ "_id" : "3", "money" : 1000, "name" : "張三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
>
cursor.sort()在cursor.skip()和cursor.limit()之前執行
> db.user.find().limit(4).skip(1).sort({money: -1,_id: 1})
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "廣州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亞", "北京" ] }
{ "_id" : "1", "money" : 1000, "name" : "劉一" }
{ "_id" : "2", "money" : 1000, "name" : "陳二" }
>
3. 文件投影
db.collection.find(<query>,<projection>)
不使用投影時,db.collection.find() 返回符合篩選條件的完整文件,而使用投影可以有選擇性地返回文件中的部分欄位
{field: inclusion}
- 1 : 表示返回欄位,
- 0 : 表示不返回欄位
只返回 name 欄位,預設情況下 _id 欄位都會返回
> db.user.find({},{name: 1})
{ "_id" : "1", "name" : "劉一" }
{ "_id" : "2", "name" : "陳二" }
{ "_id" : "3", "name" : "張三" }
{ "_id" : "4", "name" : "李四" }
{ "_id" : "5", "name" : "王五" }
{ "_id" : "6", "name" : "趙六" }
{ "_id" : "7", "name" : "孫七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "name" : "吳九" }
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "name" : "廣東人" }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "name" : "zhangsan" }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "name" : "ZHANG" }
>
只返回 name 欄位,不包含 _id 欄位
> db.user.find({},{name: 1,_id: 0})
{ "name" : "劉一" }
{ "name" : "陳二" }
{ "name" : "張三" }
{ "name" : "李四" }
{ "name" : "王五" }
{ "name" : "趙六" }
{ "name" : "孫七" }
{ "name" : "周八" }
{ "name" : "吳九" }
{ "name" : "廣東人" }
{ "name" : "zhangsan" }
{ "name" : "ZHANG" }
>
除了文件主鍵外,不可以在投影文件中混合使用包含和不包含兩種投影操作
> db.user.find({},{name: 1,_id: 0,money: 0})
Error: error: {
"ok" : 0,
"errmsg" : "Cannot do exclusion on field money in inclusion projection",
"code" : 31254,
"codeName" : "Location31254"
}
> db.user.find({},{name: 1,_id: 0,money: 1})
{ "money" : 1000, "name" : "劉一" }
{ "money" : 1000, "name" : "陳二" }
{ "money" : 1000, "name" : "張三" }
{ "money" : 1000, "name" : "李四" }
{ "money" : 1000, "name" : "王五" }
{ "money" : 1000, "name" : "趙六" }
{ "money" : 1000, "name" : "孫七" }
{ "money" : 1000, "name" : "周八" }
{ "money" : 1000, "name" : "吳九" }
{ "money" : 3000, "name" : "廣東人" }
{ "money" : 2000, "name" : "zhangsan" }
{ "money" : 2000, "name" : "ZHANG" }
>
[慕課手記同步:mongo-03-查詢文件] https://www.imooc.com/article/314364
歡迎關注文章同步公眾號"黑桃"