我們先來看看下面的表格
作用 | SQL | MongoDB |
查詢所有記錄 | SELECT * FROM users | db.users.find() |
查詢age=33的記錄 | SELECT * FROM users WHERE age=33 | db.users.find({age:33}) |
子鍵(字段)篩選 | SELECT a, b FROM users WHERE age=33 | db.users.find({age:33}, {a:1,b:1}) |
排序 | SELECT * FROM users WHERE age=33 ORDER BY name | db.users.find({age:33}).sort({name:1}) |
比大小 | SELECT * FROM users WHERE age>33 | db.users.find({'age':{$gt:33}})}) |
正則(模糊匹配) | SELECT * FROM users WHERE name LIKE "Joe%" | db.users.find({name:/^Joe/}) |
忽略、限制 | SELECT * FROM users LIMIT 10 SKIP 20 | db.users.find().limit(10).skip(20) |
Or操作 | SELECT * FROM users WHERE a=1 or b=2 | db.users.find({$or:[ {a:1} , {b:2}] }) |
僅返回1條(TOP 1) | SELECT * FROM users LIMIT 1 | db.users.findOne() |
Distinct聚合 | SELECT DISTINCT last_name FROM users | db.users.distinct('last_name') |
Count聚合 | SELECT COUNT(AGE) from users | db.users.find({age: {'$exists': true}}).count() |
查詢計劃 | EXPLAIN SELECT * FROM users WHERE z=3 | db.users.find({z:3}).explain() |
子鍵篩選
子鍵篩選也就是我們在 SQL 數據庫中見怪不怪的字段篩選。然而,由于MongoDB 采用的是基于 Json 的查詢語句,所以其子鍵篩選顯得非常怪異(限于篇幅,請留意示例代碼中的注釋):
// 包含所有子鍵
db.users.find({age:33})
// 僅包含子鍵:_id、a、b
db.users.find({age:33}, {a:1, b:1});
// 僅包含子鍵:_id、a
db.users.find({age:33}, {a:1, });
// 僅包含子鍵(這里給出了剔除_id的方法):a
db.users.find({age:33}, {a:1, b:0, });
復雜查詢
MongoDB 可以支持一些比較操作(大于小于)、子句( or )、取反( not )等查詢,同樣的,請觀察示例代碼:
// 實際上它們都是查詢操作符!
// 返回年齡大于等于33歲,且小于40歲的用戶:
db.users.find({ age: { ‘$gte’ : 33, ‘$lt’ : 40 } });
// 返回年齡大于33歲,且不等于40歲的用戶:
db.users.find({ age: { ‘$gte’ : 33, ‘$ne’ : 40 } });
// 返回年齡等于33歲,或等于40歲的用戶:
db.users.find({ ‘$or’: [ {‘age’ : 33}, {‘age’ : 40} ] });
注意:默認情況下,MongoDB執行的是and操作,即所有指定的條件都是與的關系。只有在特別的情況下,才會使用或(or),而$or就是MongoDB的或子句。
查詢條件操作符
操作符 | 說明 | 示例 |
$lt,$lte,$gt,$gte | <, <=, >, >= | db.things.find({ a: { $gt: value } } ); |
$all | 數組中的元素是否完全匹配 | db.things.find( { a: { $all: [ 2, 3 ] } } ); |
$exists | 可選:true,false | db.things.find( { a : { $exists : true } } ); |
$mod | 取模:a % 10 == 1 | db.things.find( { a : { $mod : [ 10 , 1 ] } } ); |
$ne | 取反:即not equals | db.things.find( { x : { $ne : 3 } } ); |
$nin | $in的反操作,即SQL的 NOT IN | db.things.find({j:{$nin: [2,4,6]}}); |
$nor | $or的反操作,即不匹配(a或b) | db.things.find( { name : "bob" , $nor : [ { a : 1 } , { b : 2 } ] } ) |
$or | Or子句,注意$or不能嵌套使用 | db.things.find( { name : "bob" , $or : [ { a : 1 } , { b : 2 } ] } ) |
$size | 匹配數組長度 | db.things.find( { a : { $size: 1 } } ); |
$type | 匹配子鍵的數據類型 | db.things.find( { a : { $type : 2 } } ); |
正則表達式
MongoDB 的正則表達式實現了 SQL 中的通配符匹配的機制,而且比 SQL 更加強大。不過可惜的是,只有類似于 / ^ .+/ 這樣的前綴型正則表達式才能夠使用索引,其他形式都會做全集合掃描。
MongoDB 的正則表達式語法與 JavaScript 完全一致。
// 正則匹配方法之一
db.customers.find( { name : /acme.*corp/i } );
// 正則匹配方法之二
db.customers.find( { name : { $regex : 'acme.*corp', $options: 'i' } } );
// 與其他條件聯合使用
db.customers.find( { name : { $regex : /acme.*corp/i, $nin : [‘abc'] } } );
注意:MongoDB的正則表達式可以匹配其自身。如果您將正則表達式存入了MongoDB,那么查詢的時候,它可以匹配它自身!
數組查詢
MongoDB數組查詢,除了之前提到的$all和$size等,還有:$size,$slice,子項定位和$elemMatch。
1.數組查詢之$size
$size 用來匹配數組長度(即最大下標):
/ 返回comments包含5個元素的文檔
db.posts.find({}, {comments:{‘$size’: 5}});
請注意:$size操作符并不能與其他查詢操作符(子句)聯合使用,這意味著您不能使用如下代碼:
// 以下的使用方法是錯誤的
db.posts.find({}, {comments:{‘$size’: { ‘$gt’: 5 }}});
2.
$slice 操作符類似于子鍵篩選,只不過它篩選的是數組中的項。
// 僅返回數組中的前5項
db.posts.find({}, {comments:{‘$slice’: 5}});
// 僅返回數組中的最后5項
db.posts.find({}, {comments:{‘$slice’: -5}});
// 跳過數組中的前20項,返回接下來的10項
db.posts.find({}, {comments:{‘$slice’: [20, 10]}});
// 跳過數組中的最后20項,返回接下來的10項
db.posts.find({}, {comments:{‘$slice’: [-20, 10]}});
3.
細心的童鞋已經發現,數組的子項定位已經在上一個章節講過了。是的,是講過了,但我還是要再提一下,加深印象!MongoDB 允許在查詢中指定數組的下標,以實現更加精確的匹配。
本小節有且僅有一個簡單的代碼示例:
// 返回comments中第1項的by子鍵為Abe的所有文檔
db.blogposts.find( { "comments.0.by" : "Abe" } );
4.數組查詢之$ elemmarch
童鞋們還記得上一集中我們提到的數組定位修改器中除了數組下標還有一個“$ ”符號嗎?該符號在 find 中就不靈了,怎么辦呢?那就只有考慮使用 $elemMatch 操作符了,多說無益,看代碼:
// 有這樣一個包含了2個文檔的集合,仔細觀察
// 現在我們需要找到 shape = "square" 且 color = "purple" 的那項
{ "foo" : [ { "shape" : "square", "color" : "purple", "thick" :
false }, { "shape" : "circle", "color" : "red", "thick" : true } ]};
{ "foo" : [ { "shape" : "square", "color" : "red", "thick" : true },
{ "shape" : "circle", "color" : "purple", "thick" : false } ]};
// 這兩個查詢都會同時匹配兩個文檔
db.foo.find({"foo.shape": "square", "foo.color": "purple"});
db.foo.find({foo: {"shape": "square", "color": "purple"} });
// 這才是我們想要的
db.foo.find({foo: {"$elemMatch": {shape: "square", color:
"purple"}}});
新聞熱點
疑難解答