MongoDB條件查詢
- find({查詢條件限定},{返回欄位})
這是一個查詢的基本語法,各個簽名的作用已經說得很清楚。下面來細細展開:
當然最開始插入一批資料以供測試:
- db.users.insert({"_id": 1, "name": "aroba", "age": 22, "friends": 3})
- db.users.insert({"_id": 2, "name": "brob", "age": 23, "friends": 4})
- db.users.insert({"_id": 3, "name": "robin", "age": 24, "friends": 23})
- db.users.insert({"_id": 4, "name": "ccrob", "age": 25, "friends": 32})
- db.users.insert({"_id": 5, "name": "drobin", "age": 26, "friends": 15})
- db.users.insert({"_id": 6, "name": "rrobin", "age": "az", "friends": 19})
1、 方法中的第一個引數:查詢條件限定是一個document結構,如為{}將預設返回所有資料
- #查詢一個年齡為27的使用者:
- db.users.find({"age":23})
- #查詢一個年齡為27,姓名為robin的使用者,相當於AND
- db.users.find({"age":23, "name":"brob"})
作為文件的查詢條件,可以支援更復雜的格式:
- #查詢年齡大於20且小於30的使用者
- db.users.find({"age":{"$gt":20, "$lte":23}})
這裡條件查詢有常用的:小於("$lt")、小於等於("$lte")、大於("$gt")、大於等於("$gte")、不等於("$ne") 。這些條件查詢對數字日期型別的欄位比較適用
前面說到同時查詢age和name屬性,相當於AND查詢。這裡來看看OR查詢,主要透過"$in"和"$or" 。對單一鍵有多個值與其匹配的話就用"$in",後面跟一個條件陣列。
- #查詢年齡在某個範圍的使用者:
- db.users.find({"age":{"$in":[20, 22, 25]}})
"$in" 對支援的型別非常靈活,不同型別的條件可以同時查詢。與之相對應的就是"$nin",表示不在該範圍內的鍵
- db.users.find({"age":{"$in":[20, 22, 25, "az"]}})
- db.users.find({"age":{"$nin":[20, 22, 25, "az"]}})
與單一鍵的"$in"不同的是,"$or"是包含多個可能條件的陣列。
- #年齡在某個範圍內或者name在某個範圍內的使用者
- db.users.find({"$or": [{"age": 23 }, {"name": "robin"}]})
- db.users.find({"$or": [{"age": {"$in": [ 23, 4, "az" ]} }, {"name": "robin"}]})
2、返回欄位
作為查詢的第二個引數,如果沒有的話是預設返回所有欄位。可以對需要的返回欄位指定:
- db.users.find({}, {"name":1, "age":1})
1、這個查詢會返回name、age、_id欄位
2、_id是預設返回,如果不要顯示加上("_id":0)
- db.users.find({}, {"name":1, "age":1, "_id":0})
3、如果某個欄位如age不存在,也不拋異常
4、需要顯示的欄位設定為大於零的數就可以,但還是用1好理解,但如果對不需要顯示的欄位且不是_id設定為0或其他會拋異常
- db.users.find({}, {"name":1, "age":0, "_id":0})
這樣是不行的,如果不要返回age不加上就可以了
後面還將對陣列查詢的返回欄位做相應的說明,這裡就先到此
3、幾點說明
1、"$not"元條件句,用在其他任何條件上,如
- #age>20即查詢age小於等於20的使用者
- db.user.find({"age": {"$not" : {"$gt" :20}}})
- #這裡查詢age不是1,6,11,16...等的使用者
- db.user.find({"age": {"$not": {"$mod": [5, 1]}}})
2、條件查詢與更新修改器
- #更新修改器
- db.users.update({"age": 23},{"$set":{"name":"zzzz"}})
- #條件查詢
- db.users.find({"age": {"$gt": 20}})
條件句是內層文件鍵,修改器是外層文件鍵。而且對同一個欄位age來說可以是多個限定條件,但是修改器不能對應多個
3、null
如果某個欄位的值為null,根據null來查詢時可以返回該條文件,但也會返回不包含該欄位的文件
- #新增兩條資料
- >db.users.insert{ "_id" : 7, "age" : 23, "name" : "joe" }
- >db.users.insert{ "_id" : 8, "age" : 24, "friends" : null, "name" : "sam" }
查詢鍵值為null的欄位
- >db.users.find({"friends": null})。
這裡會返回friends為null的文件,但是也會返回沒有該鍵的文件
- { "_id" : 7, "age" : 23, "name" : "joe" }
- { "_id" : 8, "age" : 24, "friends" : null, "name" : "sam" }
需要透過"$exists"來判定鍵值是否存在
- > db.users.find({"friends":{"$in":[null],"$exists":true}})
- { "_id" : 8, "age" : 24, "friends" : null, "name" : "rrbin" }
4、正規表示式
- #這裡會返回所有name中包含rob欄位的文件
- > db.users.find({"name":/rob/})
- #不僅對欄位值進行正則匹配,如果值本身是正則式也匹配
4、陣列查詢
插入幾條資料測試
- db.food.insert({"_id": 1, "fruit": ["apple", "banana", "peach"]})
- db.food.insert({"_id": 2, "fruit": ["apple", "orange"]})
- db.food.insert({"_id": 3, "fruit": ["banana", "peach", "orange"]})
以下是一些常用的查詢方法,直接上
- #匹配fruit中包含banana的文件
- db.food.find({"fruit": "banana"})
- #必須匹配所有
- db.food.find({"fruit": {"$all" : ["apple", "peach"]}})
- #精確匹配
- db.food.find({"fruit": ["apple", "orange"]})
- #指定下標 key.index
- db.food.find({"fruit.2": "peach"})
- #查詢指定長度的陣列
- db.food.find({"fruit": {"$size" : 3}})
但是"$size"操作只能嚴格匹配,遇到比如要求陣列大於或者小於之類的查詢就無能為力了。這裡提供瞭解決的方案:對文件新增size欄位,每次對陣列push或pop操作時,對size欄位做相應的增減。查詢的時候再對欄位size做相應的處理
- db.food.update({"$push" :{"fruit" : "strawberry"} , "$inc" : {"size" : 1}})
- db.food.find({"size" : {"$gt" : 3}})
返回陣列指定子集
"$slice"用於返回陣列的一個子集,支援前、後或者偏移
- db.food.insert({"_id": 4, "fruit": ["apple", "banana", "peach", "orange", "watermelon", "lemon", "cherry"]})
- #取前2個
- db.food.find({"_id":4}, {"fruit":{"$slice":2}})
- #{u'_id': 4, u'fruit': [u'apple', u'banana']}
- #取後兩個
- db.food.find({"_id":4}, {"fruit":{"$slice":-2}})
- #{u'_id': 4, u'fruit': [u'lemon', u'cherry']}
- #從第2個開始取三個,這個其實達到分頁的效果,但書中明確指出對大量資料skip效能下降厲害,不建議考慮這種方式
- db.food.find({"_id":4}, {"fruit":{"$slice":[2, 3]}})
- #{u'_id': 4, u'fruit': [u'peach', u'orange', u'watermelon']}
使用"$slice"獲取陣列內的值時,其他的鍵也會預設返回,如果不需要返回非陣列內的其他鍵這裡可以指明,與前面返回不同的是這裡可以用0
- db.food.insert({"_id": 5, "sum":7, "fruit": ["apple", "banana", "peach", "orange", "watermelon", "lemon"]})
- db.food.find({"_id":5}, {"fruit":{"$slice":[2, 3]}, "_id":0, "sum":0})
- {u'fruit': [u'peach', u'orange', u'watermelon']}
5、查詢內嵌文件
這裡主要考慮匹配查詢內嵌文件,考慮如下文件
- db.users.insert({"_id": 9, "age":23, "name": {"first":"joe", "last":"sam"}})
- db.users.insert({"_id": 10, "age":24, "name": {"first":"joe", "middle":"dd", "last":"sam"}})
查詢名字為joe sam的使用者
- #查詢名字為joe sam的使用者
- data = db.users.find({"name":{"first":"joe", "last":"sam"}})
- #返回第一條,實際上這相當於精確匹配,這個查詢條件將嚴格匹配順序、欄位的數量。其實第二條也是我們想要的結果,那麼正確的寫法應該是:
- data = db.users.find({"name.first":"joe", "name.last":"sam"})
書中說到一種複雜情況下的查詢:joe發表的5分以上的評論:
- db.blog.insert({"_id":1, "content":"....", "comments":[{"name":"joe", "score":3, "comment":"nice"}, {"name":"sam", "score":5, "comment":"zzz"}, {"name":"joe", "score":5, "comment":"good"}]})
- data = db.blog.find({"comments":{"name":"joe", "score":{"$gte":5}}})
- #這樣是查不到資料的,內嵌文件要求匹配整個文件,而不是comments鍵
- data = db.blog.find({"comments.name":"joe", "comments.score":{"$gte":5}})
- #這個查詢會返回這條記錄,其實是匹配的commets中各個鍵,即joe匹配第一條,score匹配第二條
- data = db.blog.find({"comments":{"$elemMatch":{"name":"joe", "score":{"$gte":5}}}})
6、分頁
分頁在前面說到"$slice"時,其實是達到分頁的效果,前面也說了弊端,這裡進一步說明。這裡採用limit限制返回結果,slice跳過指定數量文件,sort對查詢結果排序
limit
db.users.find().limit(3)結果集超過三條返回三條,不足返回實際數量,貌似對負數不感冒,比如-2還是返回前兩條,或者limit裡沒有偏移這個概念
skip
db.users.find().limit(3)省略結果集前三個,返回剩下的,結果集不足三個就啥都木有了,當然這個也一樣,別寫負數了,否則拋異常
sort
對結果集排序:1升序,-1降序。可支援多個鍵/對
- db.users.find().sort([("name", 1), ("age", -1)])
- db.users.find().sort({"name":1,"age":-1})
- #這就是分頁
- db.users.find().limit(2).sort("_id", 1)
- db.users.find().limit(2).skip(2).sort("_id", 1)
- db.users.find().limit(2).skip(4).sort("_id", 1)
這對大資料量的skip效能影響較大,這裡也提供了一些繞過的方法。比如先取得最後一條的記錄的某個唯一鍵,再查詢大於該鍵的值。可以看出這個限制條件挺多,當然容易想到的採用主鍵"_id",這是主鍵必須是數字了
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/27000195/viewspace-1400265/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MongoDB查詢條件MongoDB
- mongodb條件查詢不等於MongoDB
- 深入理解mongodb查詢條件語句MongoDB
- MongoDB之資料查詢(where條件過濾)MongoDB
- MongoDB操作之遍歷集和條件查詢操作MongoDB
- mysql條件查詢MySql
- Laravel 多條件查詢Laravel
- SQL多條件查詢SQL
- 條件查詢JSPJS
- golang beego orm 查詢條件 or andGolangORM
- 【mybatis-plus】條件查詢MyBatis
- 多條件查詢---ssh版本
- sql 查詢條件問題SQL
- 查詢條件封裝物件封裝物件
- Javaweb-DQL-條件查詢JavaWeb
- 寫一個“特殊”的查詢構造器 – (四、條件查詢:複雜條件)
- 34. 過濾條件、多表查詢、子查詢
- mysql拆分字串做條件查詢MySql字串
- AntDesignBlazor示例——列表查詢條件Blazor
- 查詢作為條件的SQLSQL
- 菜品條件分頁查詢
- Linq查詢之多個排序條件排序
- Linq兩個from查詢條件
- 複合條件查詢的重構
- oracle date資料的條件查詢Oracle
- 【索引】反向索引--條件 範圍查詢索引
- SQL SERVER 條件語句的查詢SQLServer
- SpringBoot Jpa多條件查詢Spring Boot
- Vue請求介面查詢條件拼接Vue
- mysql多條件過濾查詢之mysq高階查詢MySql
- mysql like查詢 - 根據多個條件的模糊匹配查詢MySql
- mongodb查詢MongoDB
- 查詢條件和條數,先查詢兩條免費的,後面為vip
- mybatis-plus QueryWrapper條件查詢器MyBatisAPP
- gorm 使用map實現in 條件查詢用法GoORM
- 讓NoSQL支援簡單條件查詢VRSQLVR
- 【索引】反向索引--條件 範圍查詢(二)索引
- RANK函式基於條件的查詢函式