我们先来看看下面的表格
作用 | 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"}}});
新闻热点
疑难解答