本篇要解決的問題
在 本機安裝好 MongoDB,也在上面建立了測試資料後,第一步最重要的,就是 CRUD(增刪查改)。
工程師最常遇到的需求,就是使用者要有的沒的資料,因此把 Read 讀取/查詢 列為系列的第二篇。
本篇主要是怎麼用命令的方式,查詢出資料庫裡的資料。
通用
列出所有 DB:
show dbs
進到指定的 collection:
use <DB名稱> use admin
清除所有 Logs:
cls
find 查詢
列出指定 collection 裡的 documents:
use <DB名稱> db.<Collection名稱>.find() use bookstore db.books.find()
MongoDB Shell 預設提供的會是前 20 筆,而不會整個 documents 全部撈出來,主要是防止遇到有幾百萬筆 documents 時,一次要全撈出來會有悲催事件發生。
如果想繼續看之後的 20 筆,輸入 it 就可以。
若想要一次撈更多的資料,突破 20 筆的限制,就用 limit(想要的筆數):
db.books.find().limit(30)
這樣出來的資料最多就是 30 筆,而不是預設的 20 筆。
加上條件
filter 出 collection 裡符合條件的 documents:
db.<Collection名稱>.find({ 條件 })
db.books.find({ author: "August" })
db.books.find({ author: "August", rating: 10 })只顯示想要的字段
filter 出 collection 裡符合條件的 documents,而且只顯示指定的字段:
db.<Collection名稱>.find({ 條件 }, { 字段: 0(排除)、1(包含) })
db.books.find({ author: "August" }, { title: 1, author: 1 })字段的數字,預設值是 0,意思是排除這個字段,1 代表包含這個字段。
比方我們的 books 資料如下:
{
_id: ObjectId('65bba54cee4e5a09b7d87f3f'),
title: "Let's Write",
author: "August",
pages: 500,
rating: 10
}我們寫了 { title: 1, author: 1 },代表查詢結果包含 title、author,而另外二個字段 pages、rating 沒有寫,因此預設是 0(排除),所以最後查詢結果就是:
{
_id: ObjectId('65bba54cee4e5a09b7d87f3f'),
title: "Let's Write",
author: "August",
}要注意的是,除非特別指定 _id: 0,否則 _id 字段會一直被包含在結果中。
documents 裡,只顯示想看到的字段:
db.<Collection名稱>.find({}, { 字段: 1 })
db.books.find({}, { title: 1 })這個算是前二個的組合計,{} 代表所有 documents,{ title: 1 } 代表顯示結果只包含 title,其它排除。
count 顯示結果筆數
count 顯示結果有幾筆:
db.<Collection名稱>.find().count() db.books.find().count()
sort 排序方式
sort 以什麼字段,由小到大或由大到小排列:
db.<Collection名稱>.find().sort({ 字段: 1(由小到大)、-1(由大到小) })
db.books.find().sort({ rating: 1 })sort 的字段可以多個,MongoDB 會照字段的順序去排列。
比方我們寫 { rating: 1, title -1 },就會先照 rating 由小到大排,遇到相同的 rating,再用 title 由大到小排。
運算子 Operators
運算子都由 $ 符號為開頭。
因為對 JS 比較熟,所以看到像 MongoDB 中 $gt 這種寫法有點不習慣,因此這邊會加上「類似於 JS 的 ……」來做比對,加深記憶。
大於、小於
$gt(大於)、$gte(大於等於)、$lt(小於)、$lte(小於等於)。
db.books.find({ rating: { $gt: 7 } }); # rating 大於 7
db.books.find({ rating: { $gte: 7 } }); # rating 大於等於 7
db.books.find({ rating: { $lt: 6 } }); # rating 小於 6
db.books.find({ rating: { $lte: 6 } }); # rating 小於等於 6or、and 條件
{ $or: [{}, {}, {} ...] },符合其中一個條件的就可以。{ $and: [{}, {}, {} ...] },所有條件都要符合。
db.books.find({
$or: [
{ rating: 8 },
{ rating: 9 }
]
});
# 類似於 JS 的:if(rating === 8 || rating === 9)
db.books.find({
$and: [
{ pages: { $gt: 500 }},
{ pages: { $lte: 700 }}
]
})
# 類似於 JS 的:if(pages > 500 && pages <= 700)includes、not includes
$in: []:像 JS 的 some(),查詢出符合陣列裡任一值的。$nin: []:像 JS 的 !some(),查詢的結果會排除陣列裡任一值的。
db.books.find({
rating: { $in: [7,8,9] }
});
# 類似於 JS 的:const result = books.some(book => [7,8,9].includes(book.rating));
db.books.find({
rating: { $nin: [1,2,3] }
});
# 類似於 JS 的:const result = !books.some(book => [1,2,3].includes(book.rating));Nested Documents 的查詢
值為陣列
假設有資料是陣列(下面的 genres):
{
"_id": { "$oid": "65bba54cee4e5a09b7d87f3f" },
"genres": ["fantasy", "history", "comedy"]
}查找 genres 陣列裡,是否包含單一值:
db.books.find({ genres: "fantasy" })因為範例資料是 "genres": ["fantasy", "history", "comedy"],包含了 fantasy,因此結果會顯示出來。
如果只想找 genres 就只有 fanstasy 的結果,就改成:
db.books.find({ genres: ["fantasy"] })我們的範例資料除了 fanstasy,還有 history、comedy,就不符合查詢條件。
如果想查出包含 2 個以上的值,用 $all:
db.books.find({
genres: {
$all: ["fantasy", "history"]
}
})
# 類似於 JS 的:const result = book => ["fantasy", "history"].every(genre => book.genres.includes(genre));我們的範例資料包含了 fantasy、history,因此結果會顯示出來。
Nested 資料
假設有資料是 Nested 的(下面的 reviews):
{
"_id": {
"$oid": "65bba54cee4e5a09b7d87f3f"
},
"reviews": [
{ "name": "August", "body": "Good" },
{ "name": "Zena", "body": "Good" }
]
}查詢時,用 . 連接,比方我們要查 reviews 的 name 是 August 的:
db.books.find({ "reviews.name": "August" })findOne
上面的 find 改成 findOne,就會由一次最多 20 筆,改成只顯示 1 筆。


