前置知識
find 語法
格式:db.COLLECTION_NAME.find(query, projection)
參數説明:
- query:可選,使用查詢操作符指定的查詢條件。
- projection:可選,使用投影操作符指定返回的鍵。如果要在查詢時返回文檔中所有鍵值,只需省略該參數即可(默認為省略)。
文檔查詢條件的構造可以參考下表所示。
| 操作 | 格式 | 範例 |
|---|---|---|
| 等於 | {<key>:<value>} | db.col.find({"by":"x"}) |
| 小於 | {<key>:{$lt:<value>}} | db.col.find("likes":{$lt:50}}) |
| 小於等於 | {<key>:{$lte:<value>}} | db.col.find(("likes":{$lte:50}}) |
| 大於 | {<key>:{$gt:<value>}} | db.col.find("likes":{$gt:50}}) |
| 大於等於 | {<key>:{$gte:<value>}} | db.col.find("likes":{$gte:50}}) |
| 不等於 | {<key>:{$ne:<value>}} | db.col.find("likes":{$ne:50}}) |
| 包含 | {<key>:{$in:[<value1>,...,<valueN>]}} | db.col.find("likes":{$in:[2,3,4]}}) |
| 不包含 | {<key>:{$nin:[<value1>,...,<valueN>]}} | db.col.find("likes":{$nin:[2,3,4]}}) |
| 非 | {<key>:{$not:query}} | db.col.find("likes":{$not:{$lt:50}}}) |
解釋 非:where not likes < 50
aggregate() 聚合
db.COLLECTION_NAME.aggregate()
- $sum:
- $avg
- $min
- $max
- $first
-
$last:根據資源文檔的排序獲取最後一個文檔數據
db.mycol.aggregate([{$group:{_id:"$by_user", last_url:{$last:"$url"}}}])
可以使用 limit、skip、sort 限制返回結果數量、忽略一定數量結果、執行排序處理。
數據準備
創建實驗數據集合
itmes 集合,保存訂單信息。
db
db.createCollection("items")
插入文檔數據
pnumber:商品編號
quantity:商品數量
price:商品價格
db.items.insertMany([
{"quantity":2,"price":5.0, "pnumber":"p003"},
{"quantity":2,"price":8.0, "pnumber":"p002"},
{"quantity":1,"price":4.0, "pnumber":"p002"},
{"quantity":2,"price":4.0, "pnumber":"p001"},
{"quantity":4,"price":10.0, "pnumber":"p003"},
{"quantity":10,"price":20.0, "pnumber":"p001"},
{"quantity":10,"price":20.0, "pnumber":"p003"},
{"quantity":5,"price":10.0, "pnumber":"p002"}
])
格式化顯示文檔
db.items.find().pretty()
文檔查詢操作
(1) countDocuments()
統計集合中總共多少文檔
db.items.countDocuments({})
(2) distinct()
使用 distinct 命令查詢指定鍵的所有不同值,使用時必須指定集合和鍵。
例如,對 price 鍵使用 distinct,會得到所有不同的價格。
db.runCommand({"distinct":"items","key":"price"})
(3) 單條件查詢
例如,查詢價格大於5的商品數據,大於使用 gt 操作符,操作符前面要帶上 $ 符號。
db.items.find({price:{$gt:5}})
(4) 多條件查詢
多條件組合查詢,各個條件之間默認是 AND 關係。
例如,查詢 quantity 為 10 且價格大於等於 5 的商品數據。
db.items.find({quantity:10,price:{$gte:5}})
也可以使用 $or 來進行多條件查詢,語法格式如下:
db.collectionName.find(
{
$or:[
{key:value},
{key:value}
]
})
例如,查詢 quantity 為 10 或價格大於等於 5 的商品數據。
db.items.find({$or:[{quantity:10},{price:{$gte:5}}]})
還可以將 AND 和 OR 聯合使用。
例如,查詢 pnumber 為"p003"且 quantity 為 10 或價格大於等於 5 的商品數據
db.items.find({
pnumber:"p003",
$or:[
{quantity:10},
{price:{$gte:5}}
]
})
(5) $in 查詢
例如,要找出 quantity為2、4、5的文檔。
db.items.find({quantity:{$in:[2,4,5]}})
$nin 將返回與數組中所有條件都不匹配的文檔。
要是想返回所有 quantity 不是2、4、5 的文檔,就可以用:
db.items.find({quantity:{$nin:[2,4,5]}})
説明
值得注意的是,$in能對單個鍵做OR查詢,但是要對多個鍵做查詢就得使用$or。
使用普通的AND型查詢時,總是希望儘可能用最少的條件來限定結果的範圍。OR型查詢正好相反,第一個條件應該儘可能匹配更多的文檔,這樣才是最為高效的。
$or 操作符在任何情況下都會正常工作,而如果查詢優化器可以更高效地處理$in,則應該優先選擇使用$in操作符。
(6) $not 查詢
以取模運算符 $mod 為例,$mod 會將查詢的值除以第一個給定值,若餘數等於第二個給定值則匹配成功。
例如,要查詢 quantity 值為奇數的文檔。
db.items.find({quantity:{$mod:[2,1]}})
要查詢 quantity 值為偶數的文檔,添加 $not
db.items.find({quantity:{$not:{$mod:[2,1]}}})
(7) null 查詢
null 不僅會匹配值為 null 的文檔,還會匹配不包含這個鍵的文檔(即返回缺少這個鍵的所有文檔)。
如果僅想匹配鍵值為 null 的文檔,則既要檢查該鍵的值是否為null,還要通過 $exists 條件判定鍵值已存在。
db.item.find({price:{$in:[null],$exists:true}})
由於沒有$eq(等於)操作符,所以這條查詢語句看上去麻煩,但是與只有一個元素的$in效果一樣。
(8) aggregate 聚合查詢
使用group可以執行更復雜的聚合。先選定分組所依據的鍵,而後MongoDB就會將集合依據選定鍵的不同值分成若干組。然後可以對每一個分組內的文檔進行聚合,最後可以得到一個結果文檔。
例如,統計訂單中所有商品的數量,即統計quantity的總和。
db.items.aggregate([{
$group:{_id:null,total:{$sum:"$quantity"}}
}])
例如,通過產品類型來進行分組,然後在統計賣出的數量。
db.items.aggregate([{
$group:{_id:"$pnumber",total:{$sum:"$quantity"}}
}])
例如,通過相同的產品類型來進行分組,然後查詢相同產品類型中賣出最多的訂單詳情。
db.items.aggregate([{
$group:{_id:"$pnumber",max:{$max:"$quantity"}}
}])
例如,通過相同的產品類型來進行分組,然後查詢每個訂單詳情相同產品類型賣出的平均價格。
db.items.aggregate([{
$group:{_id:"$pnumber",price:{$avg:"$price"}}
}])
(9) 管道的使用
例如,希望先通過相同的產品類型來進行分組,統計出各個產品的數量,然後再獲取最大的數量,可以使用下面的命令。
db.items.aggregate([
{
$group:{_id:"$pnumber",total:{$sum:"$quantity"}}
},
{
$group:{_id:null, max:{$max:"$total"}}
}
])
(10) 查詢選項
1. limit
限制返回結果
db.items.find().limit(3)
2. skip
丟棄結果集中的前n個文檔,將剩餘文檔作為結果返回。在“普通”查詢中,如果需要跳過大量的數據,那麼這個操作符的效率會很低,因為它必須要先匹配到所有需要跳過的文檔,然後再將這些文檔丟棄。
例如,跳過前3個結果文檔,可以使用如下命令。
db.items.find().skip(3)
3. sort
接受一個對象作為參數,該對象是一組鍵/值對。
- 鍵對應文檔的鍵名
- 值代表排序的方向,排序方向可以是1(升序)或者-1(降序)
- 如果指定了多個鍵,則按照這些鍵被指定的順序逐個排序。
例如,要按照pnumber升序以及 price降序排序,可以使用下面的命令。
db.items.find().sort({pnumber:1, price:-1})
4. 分頁
當點擊“下一頁”希望看到更多的結果時,可以通過skip非常簡單地實現,只需要略過前3個結果即可(因為前3個已經在第一頁顯示了)
db.items.find().limit(3).skip(3).sort({price:-1})