MongoDB 数据查询操作
目录MongoDB 查询操作实例简介 find() 以及投影操作关系运算查询(大于、小于、等于...)模糊查询范围查询($in,$nin)逻辑运算查询(或者 $or、等于 $and、非或者 $nor 以及 $not)存在查询(存在 $exists、null 查询)嵌套查询以及 "$all"、"$size"取模查询($mod)"$where"
目录
逻辑运算查询(或者 $or、等于 $and、非或者 $nor 以及 $not)
MongoDB 查询操作
MongoDB 查询文档使用 find() 方法。find() 方法以非结构化的方式来显示所有文档。
语法
MongoDB 查询数据的语法格式如下:
db.collection.find(query, projection)
- query :可选,使用查询操作符指定查询条件
- projection :可选,使用投影操作符指定返回的键。(通俗点讲就是:设置显示字段)
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
db.collection.find(query, projection).pretty()
实例
简介 find() 以及投影操作
最简单直接的方式:find() 查询
# 语法
db.collection.find()
# 示例
db.logs.find()
查询出指定条件的数据:
# 语法
db.collection.find({"key" : "value"})
# 示例
db.logs.find({"id" : "123456"})
隐藏掉不想显示的字段:projection 操作
不想显示的字段就设置为0,显示的字段设置为1(默认为显示,可以不用设置)
# 语法
db.collection.find({"key" : "value"}, {"key": 0 }})
# 示例 (不想显示 _id 字段)
db.logs.find({"id" : "123456"}, {"_id": 0 })
关系运算查询(大于、小于、等于...)
在 MongoDB 里面支持的关系查询操作:
大于($gt)、小于($lt)、大于等于($gte)、小于等于($lte)、不等于($ne)
示例一:查询性别为男的员工
db.emp.find({"sex":"男"}).pretty()
示例二:查询年龄大于 19 岁的员工
db.emp.find({"age": {"$gt":19}}).pretty()
示例三:查询年龄大于 19 岁的员工
db.emp.find({"age": {"$gt":19}}).pretty()
示例四:查询工资小于 6000 的员工
db.emp.find({"wages": {"$lt": 6000}}).pretty()
示例五:查询工资大等于 6000 的员工
db.emp.find({"wages": {"$gte": 6000}}).pretty()
示例六:查询年龄大于 19 岁的员工
db.emp.find({"age": {"$gt":19}}).pretty()
示例七:查询姓名不是 王五的员工
db.emp.find({"name": {"$ne": "王五" }}).pretty()
模糊查询
查询 title 包含"教"字的文档:
db.col.find({title:/教/})
查询 title 字段以"教"字开头的文档:
db.col.find({title:/^教/})
查询 title字段以"教"字结尾的文档:
db.col.find({title:/教$/})
范围查询($in,$nin)
范围之中 $in, 不在范围之中 $nin
$in
匹配键值等于指定数组中任意值的文档。类似于 SQL 中的 in 操作。
db.col.find({ field: { $in: [<value1>, <value2>, ... <valueN> ] } })
$nin
匹配键值不存在或者不等于指定数组中任意值的文档。类似于 SQL 中的 not in 操作。
db.col.find({ field: { $nin: [<value1>, <value2>, ... <valueN> ] } })
示例:查询姓名是 “张三”、“李四”、“王五” 的信息
db.emp.find( {"name": {"$in": ["张三", "李四", "王五" ] } } )
示例:查询姓名不是 “张三”、“李四”、“王五” 的信息
db.emp.find( {"name": {"$nin": ["张三", "李四", "王五" ] } } )
逻辑运算查询(或者 $or、等于 $and、非或者 $nor 以及 $not)
$or
db.col.find( { $or: [ {key1: value1}, {key2:value2} ] } ).pretty()
示例:查询年龄大于 19岁, 或者工资大于 6000 的员工
db.emp.find( {"$or": [ {"age": {"$gt" : 19} }, {"wages": {"$gt": 6000 } } ] }).pretty()
$and
在进行逻辑运算的时候 “and” 操作是最容易,直接使用 “,”分割即可。
# 语法 db.col.find( { $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] } )
示例一:查询 年龄在 19 ~ 25 之前的员工
db.emp.find({"age": {"$gte": 19, "$lte": 25 }})
示例二:查询 名字为 王五,工资大于 5000 的员工
对于下面使用逗号分隔符的表达式列表,MongoDB会提供一个隐式的 $and 操作
//等同于{ $and: [ { "name": "王五" }, { "wages": { "$lt" :5000 } } ] }
db.emp.find({ "name": "王五" , "wages": { "$lt":5000 }} )
$nor
执行逻辑NOR运算,指定一个至少包含两个表达式的数组,选择出都不满足该数组中所有表达式的文档。
db.col.find( { $nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] } )
示例:查询 name 不为 “王麻子”,工资不小于 5000 的文档记录
db.emp.find( { "$nor": [ { "name" : "王麻子" }, { "wages": { "$lt": 5000 } } ] } )
$not
执行逻辑NOT运算,选择出不能匹配表达式的文档 ,包括没有指定键的文档。$not 操作符不能独立使用,必须跟其他操作一起使用(除 $regex)。
db.col.find( { field: { $not: { <operator-expression> } } } )
示例:查询 工资不大于 5000 (即工资小于等于 5000) 的文档数据
db.emp.find( { "wages": { "$not": { "$gt": 50 } } } ) //等同于db.emp.find( { "wages": { "$lte": 50 } } )
存在查询(存在 $exists、null 查询)
$exists
如果 $exists 的值为true,选择存在该字段的文档;若值为 false 则选择不包含该字段的文档。
// 语法
db.col.find( { field: { $exists: <boolean> } } )
示例:
// 查询不存在 wages 字段的文档(所有文档)
db.emp.find( { "wages": { "$exists" : false } })
// 查询 amount 字段存在,且值不等于 5000 和 6000 的文档
db.emp.find( { "wages": { "$exists" : true, $nin: [ 5000, 6000 ] } }
如果该字段的值为 null,$exists 的值为 true 会返回该条文档,false 则不返回。
// 向集合中插入一条 wages 键值为 null 的文档
{"name":"test4","wages": null}
// 0条数据
db.inventory.find( { amount: { $exists: false } } )
// 所有的数据
db.inventory.find( { amount: { $exists: true } } )
由此可以看到:$exists 操作,仅仅只是判断 key 是否存在,而不去判断值是否为 null。
null 查询
如何检索出sex键值为null的文档,我们使用"in"、"where" 操作符,"$in" 判断键值是否为 null, "$exists" 判定集合中文档是否包含该键。
// 集合中有一条sex键值为null的文档
{"name":"xiaoming","age":20,"sex":"male"}
{"name":"xiaohong","age":22,"sex":"female"}
{"name":"lilei","age":24,"sex":null}
// 返回文档中存在sex键,且值为null的文档
db.users.find({ "sex":{ "$in": [null], "$exists":true }})
// 返回文档中存在birthday键,且值为null的文档
// 文档没有birthday键,所以结果为空
db.users.find({ "birthday" : { "$in": [null], "$exists" :true }})
另外一种查询方式:
db.users.find({ "sex" : null})
// 等同于
db.users.find({ "sex" :{ "in" :[null], "exists" : true }})
嵌套查询以及 "$all"、"$size"
嵌套查询:是指当我们的节点中存在子节点时,针对于子节点的查询操作
$all 查询:匹配那些指定键的键值中包含数组。
$size 查询:用其查询指定长度的数组。
嵌套查询
查询文档有两种方式,一种是完全匹查询,另一种是针对 键/值对 查询。
// 我们的数据库中的数据
{ "name" : { "first" : "test1", "last" : "test2" } }
内嵌文档的完全匹配查询和数组的完全匹配查询一样,内嵌文档内键值对的数量,顺序都必须一致才会匹配:
> db.user.find({ name : { first : "test1", last : "test2" } });
{ "_id" : ObjectId("98d7b0d438962e1a2k7296d5"), "name" : { "first" : "test1", "last" : "test2" } }
>
//无任何返回值
> db.user.find({ name : { last : "test2" , first : "test1"} });
>
推荐采用针对键/值对查询,通过点表示法来精确表示内嵌文档的键:
//查询结果一样
db.profile.find({ "name.first" : "test1" , "name.last" : "test2"});
//或者
db.profile.find({ "name.last" : "test2" , "name.first" : "test1"} );
"$all"
匹配那些指定键的键值中包含数组,而且该数组包含条件指定数组的所有元素的文档,数组中元素顺序不影响查询结果。
// 语法
db.col.find({ field: { $all: [ <value> , <value1> ... ] })
首先,我们先插入一点数据:
{"name":"t1", "amount":16, "tags":[ "school", "book", "bag", "headphone", "appliances" ]}
{"name":"t2", "amount":50, "tags":[ "appliances", "school", "book" ]}
{"name":"t3", "amount":58, "tags":[ "bag", "school", "book" ]}
查询出在集合inventory中 tags键值包含数组,且该数组中包含appliances、school、 book元素(必须要是全部包含)的所有文档:
db.inventory.find( { tags: { $all: [ "appliances", "school", "book" ] } } )
// 查出的结果
[ "school", "book", "bag", "headphone", "appliances" ]
[ "appliances", "school", "book" ]
文档中键值类型不是数组,也可以使用$all操作符进行查询操作,如下例所示 "$all" 对应的数组只有一个值,那么和直接匹配这个值效果是一样的。
//查询结果是相同的,匹配amount键值等于50的文档
db.inventory.find( { amount: {$all:[50]}} )
db.inventory.find( { amount: 50}} )
要是想查询数组指定位置的元素,则需使用key.index语法指定下标,例如下面查询出tags键值数组中第2个元素为"school"的文档:
db.inventory.find({"tags.1":"school"})
"$size"
用其查询指定长度的数组。
// 语法
db.col.find({field: {$size: value} })
查询集合中tags键值包含有3个元素的数组的所有文档:
db.inventory.find({ tags : { $size : 3 }})
// 查询的结果
{"name":"t2", "amount":50, "tags":[ "appliances", "school", "book" ]}
{"name":"t3", "amount":58, "tags":[ "bag", "school", "book" ]}
size必须制定一个定值,不能接受一个范围值,不能与其他查询子句组合(比如"gt")。但有时查询需求就是需要一个长度范围,这种情况创建一个计数器字段,当你增加元素的同时增加计数器字段值。
//每一次向指定数组添加元素的时候,"count"键值增加1(充当计数功能)
db.collection.update({ $push : {field: value}, $inc :{count : 1}})
//比较count键值实现范围查询
db.collection.find({count : {$gt:2}})
取模查询($mod)
匹配字段值对(divisor)取模,值等于(remainder)的文档。
// 语法
db.col.find({ field: { $mod: [ divisor, remainder ]} })
// 通俗的理解为:
{ field: { $mod: [ 数字, 小数位 ]} }
示例:查询集合中 amount 键值为 4 的 0 次模数的所有文档,例如 amount 值等于 16 的文档
db.inventory.find( { amount: { $mod: [ 4, 0 ] } } )
// 查询结果
{"name":"t1", "amount":16, "tags":[ "school", "book", "bag", "headphone", "appliances" ]}
正则查询($regex)
操作符查询中可以对字符串的执行正则匹配。 MongoDB使用Perl兼容的正则表达式(PCRE)库来匹配正则表达式.
# 语法
## 基础语法
{key: 正则标记}
## 完整语法
{key: {"$regex": 正则标记, "$options": 选项}}
对于 options 主要是设置正则的信息查询的标记:
- "i": 忽略字母大小写
- "m": 忽多行查找
- "x": 空白字符串除了被转义的或在字符类中意外的完全被忽略
- "s":匹配所有的字符(圆点,“.”),包括换行内容
如果是直接使用(javaScript)那么只能够使用 "i" 与 "m",而 "x" 和 "s" 必须使用 "$regex"。
//查询name键值以“4”结尾的文档
db.inventory.find( { name: /.4/i } );
db.inventory.find( { name: { $regex: '.4', $options: 'i' } } );
"$where" 查询
操作符功能强大而且灵活,他可以使用任意的JavaScript作为查询的一部分,包含JavaScript表达式的字符串或者JavaScript函数。
新建fruit集合并插入如下文档:
//插入两条数据
db.fruit.insert({"apple":1, "banana": 4, "peach" : 4})
db.fruit.insert({"apple":3, "banana": 3, "peach" : 4})
比较文档中的两个键的值是否相等.例如查找出banana等于peach键值的文档(4种方法):
//JavaScrip字符串形式
db.fruit.find( { $where: "this.banana == this.peach" } )
db.fruit.find( { $where: "obj.banana == obj.peach" } )
//JavaScript函数形式
db.fruit.find( { $where: function() { return (this.banana == this.peach) } } )
db.fruit.find( { $where: function() { return obj.banana == obj.peach; } } )
查出文档中存在的两个键的值相同的文档,JavaScript函数会遍历集合中的文档:
>db.fruit.find({$where: function () {
for (var current in this) {
for (var other in this) {
if (current != other && this[current] == this[other]) {
return true;
}
}
}
return false;
}});
注意:我们尽量避免使用"Where"査询,因为它们在速度上要比常规査询慢很多。每个文档都要从BSON转换成JavaScript对象,然后通过"where"的表达式来运行;同样还不能利用索引。
附:
更多操作查看官网链接:https://docs.mongodb.com/manual/reference/operator/query/
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)