《MongoDB管理与开发精要》——3.1节查询操作符

简介: 本节书摘来自华章社区《MongoDB管理与开发精要》一书中的第3章,第3.1节查询操作符,作者:红 丸,更多章节内容可以访问云栖社区“华章社区”公众号查看

3.1 查询操作符
操作符就是对数据进行操作的符号,其表达了要对数据执行的操作。数据库系统的每一条查询指令都有一个操作符,表示该指令应该执行什么性质的操作。

  1. 条件操作符
    最常用也是最简单的操作符<、<=、>、>=如下面的代码所示:
//field 大于 value
db.collection.find({"field":{$gt:value}});
//field 小于 value
db.collection.find({"field":{$lt:value}});
//field 大于等于 value
db.collection.find({"field":{$gte:value}});
//field 小于等于 value
db.collection.find({"field":{$lte:value}});
如果要同时满足多个条件,可以如下面的代码所示:
//value1 < field < value2
db.collection.find({"field":{$gt:value1,$lt:value2}});
  1. $all匹配所有
    此操作符跟SQL语法的in类似,不同的是in只需要匹配括号内的某一个值,而$all必须满足括号内的所有值,如下面的代码所示:
db.users.find({age:{$all:[6, 8]}});
上例可以查询出以下文档:
{name: 'David', age: 26, age: [ 6, 8, 9 ] }
但查询不出以下这条文档:
{name: 'David', age: 26, age: [ 6, 7, 9 ] }
  1. $exists判断字段是否存在
    此操作符用于判断某个字段是否存在,例如查询所有存在age字段的记录,如下面的代码所示:
db.users.find({age: {$exists: true}});
查询所有不存在name字段的记录,如下面的代码所示:
db.users.find({name: {$exists: false}});
接下来举一个实际的例子,c1表的数据如下面的代码所示:
> db.c1.find();
{ "_id" : ObjectId("4fb4a773afa87dc1bed9432d"), "age" : 20, "length" : 30 }
{ "_id" : ObjectId("4fb4a7e1afa87dc1bed9432e"), "age_1" : 20, "length_1" : 30 }
查询存在字段age的数据,如下面的代码所示:
> db.c1.find({age:{$exists:true}});
{ "_id" : ObjectId("4fb4a773afa87dc1bed9432d"), "age" : 20, "length" : 30 }

通过实验结果可以看出只显示了age字段的数据,age_1的数据并没有显示出来。

  1. null值处理
    此操作符用于处理null值,null值的处理稍微复杂,如下面的代码所示:
> db.c2.find()
{ "_id" : ObjectId("4fc34bb81d8a39f01cc17ef4"), "name" : "Lily", "age" : null }
{ "_id" : ObjectId("4fc34be01d8a39f01cc17ef5"), "name" : "Jacky", "age" : 23 }
{ "_id" : ObjectId("4fc34c1e1d8a39f01cc17ef6"), "name" : "Tom", "addr" : 23 }
其中,“Lily”的age字段为空,“Tom”没有age字段,想找到age为空的行如下面的代码所示:
> db.c2.find({age:null}) 
{ "_id" : ObjectId("4fc34bb81d8a39f01cc17ef4"), "name" : "Lily", "age" : null }
{ "_id" : ObjectId("4fc34c1e1d8a39f01cc17ef6"), "name" : "Tom", "addr" : 23 }
奇怪的是,我们以为只能找到“Lily”,但“Tom”也被找出来了,所以“null”不仅能找到它自身,也能找到不存在age字段的记录。那么怎么样才能只找到“Lily”呢?用exists来限制一下即可,如下面的代码所示:
> db.c2.find({age:{"$in":[null], "$exists":true}})
{ "_id" : ObjectId("4fc34bb81d8a39f01cc17ef4"), "name" : "Lily", "age" : null }

跟期望的结果一样,只有“Lily”被找出来了。

  1. $mod取模运算
    此操作符用于取模运算。例如查询age取模10等于1的数据,如下面的代码所示:
db.student.find( { age: { $mod : [ 10 , 1 ] } } )
接下来举一个实际的例子,c1表的数据如下面的代码所示:
> db.c1.find()
{ "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 }
查询age取模6等于1的数据,如下面的代码所示:
> db.c1.find({age: {$mod : [ 6 , 1 ] } })
{ "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 }

可以看出,只显示age取模6等于1的数据,其他不符合规则的数据并没有显示出来。

  1. $ne不等于
    此操作符用于布尔不等于的运算。例如查询x的值不等于3的数据,如下面的代码所示:
db.things.find( { x : { $ne : 3 } } );
接下来举一个实际的例子,c1表的数据如下面的代码所示:
> db.c1.find()
{ "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 }
查询age的值不等于7的数据,如下面的代码所示:
> db.c1.find( { age : { $ne : 7 } } )
{ "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 }

可以看出,只显示age不等于7的数据,age等于7的数据没有显示出来。

  1. $in包含
    此操作符与SQL标准语法的用途一样,即要查询的数据在一个特定的取值范围内。

例如,查询x的值在2、4、6范围内的数据,如下面的代码所示:

db.things.find({x:{$in: [2,4,6]}});
接下来举一个实际的例子,c1表的数据如下面的代码所示:
> db.c1.find()
{ "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 }
查询age的值在7、8范围内的数据,如下面的代码所示:
> db.c1.find({age:{$in: [7,8]}})
{ "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 }

可以看出只显示age等于7或8的数据,其他不符合规则的数据并没有显示出来。

  1. $nin不包含
    此操作符与SQL标准语法的用途是一样的,即要查询的数据在一系列枚举值的范围外。

查询x的值在2、4、6范围外的数据,如下面的代码所示:

db.things.find({x:{$nin: [2,4,6]}});
接下来举一个实际的例子,c1表的数据如下面的代码所示:
> db.c1.find()
{ "_id" : ObjectId("4fb4af85afa87dc1bed94330"), "age" : 7, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af89afa87dc1bed94331"), "age" : 8, "length_1" : 30 }
{ "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 }
查询age的值在7、8范围外的数据,如下面的代码所示:
> db.c1.find({age:{$nin: [7,8]}})
{ "_id" : ObjectId("4fb4af8cafa87dc1bed94332"), "age" : 6, "length_1" : 30 }

通过结果可以看出只显示age不等于7或8的数据,其他不符合规则的数据并没有显示出来。

  1. $size匹配数组元素个数
    此操作符用于统计数组中的元素个数。例如,对于记录:
{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }
它匹配以下查询:
db.users.find({favorite_number: {$size: 3}})
但不匹配以下查询:
db.users.find({favorite_number: {$size: 2}})
10. count查询记录条数
此操作符用于统计记录的条数。如下面的代码所示:
db.users.find().count();
以下返回的不是5,而是user表中所有记录的数量,如下面的代码所示:
db.users.find().skip(10).limit(5).count();
如果要返回限制之后的记录数量,要使用count(true)或者count(非0) ,如下面的代码所示:
db.users.find().skip(10).limit(5).count(true);
接下来举一个实际的例子,c1表的数据如下面的代码所示:
> db.c1.find()
{ "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 }
{ "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 }
查询c1表的数据量,如下面的代码所示:
> db.c1.count()
2

通过结果可以看出,表中共有2条数据。

  1. skip限制返回记录的起点
    此操作符用于过滤结果集中的某些行。例如,从第3条记录开始,返回5条记录 ,如下面的代码所示:
db.users.find().skip(3).limit(5);
接下来举一个实际的例子,c1表的数据如下面的代码所示:
> db.c1.find()
{ "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 }
{ "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 }
查询c1表的第2条数据,如下面的代码所示:
> db.c1.find().skip(1).limit(1)
{ "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 }

通过结果可以看出,表中第2条数据被显示了出来。

  1. sort排序
    此操作符用于将结果集排序。例如,以年龄升序(asc)排列,如下面的代码所示:
db.users.find().sort({age: 1});
以年龄降序(desc)排列,如下面的代码所示:
db.users.find().sort({age: -1});
接下来举一个实际的例子,c1表的数据如下面的代码所示:
> db.c1.find()
{ "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 }
{ "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 }
查询c1表按age升序排列,如下面的代码所示:
> db.c1.find().sort({age: 1})
{ "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 }
{ "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 }
通过结果可看到第1条是age=10的,而后按升序排列结果集。
查询c1表按age降序排列,如下面的代码所示:
> db.c1.find().sort({age: -1})
{ "_id" : ObjectId("4fb5faaf6d0f9d8ea3fc91a8"), "name" : "Tony", "age" : 20 }
{ "_id" : ObjectId("4fb5fab96d0f9d8ea3fc91a9"), "name" : "Joe", "age" : 10 }

通过结果可看到第1条是age=20的,而后按降序排列结果集。

  1. distinct去掉重复值
    在表中可能会包含重复值,distinct操作符用来过滤掉多余的重复记录, 对于重复记录只保留一条。通常用它来返回不重复记录的条数,如下面的代码所示:
> db.t2.find()
{ "_id" : ObjectId("4e023565b42bc90ec25b7c07"), "name" : "Tom", "age" : 20 }
{ "_id" : ObjectId("4e023565b42bc90ec25b7c08"), "name" : "Jerry", "age" : 20 }
{ "_id" : ObjectId("4e023566b42bc90ec25b7c09"), "name" : "Rose", "age" : 18 }
>
> db.t2.distinct("name")
[ "Tom", "Jerry", "Rose" ]
>
> db.t2.distinct("age")
[ 20, 18 ]
>

name的不重复值为3个,age的不重复值为2个,调用distinct操作符后,返回一个列表,里面包含了不重复值的枚举值。
注意 这种操作在数据量较大的表里会比较耗时,请慎重使用这个功能。

  1. group分组统计
  2. by子句主要用于对where中得到的结果进行分组。也就是说,它在where子句之后执行,对经过where筛选后的结果按照某些列进行分组,之后进行相应的处理工作。

当使用聚集函数的时候,除非对整个语句的查询结果集进行聚集运算,否则都要通过指定group by子句来确定是对某类结果集进行聚集运算,如下面的传统SQL代码所示:

select a,b,sum(c) csum from coll where active=1 group by a,b

上面的语句用MongoDB也是可以实现的,如下面的代码所示:

db.coll.group(
           {key: { a:true, b:true },
            cond: { active:1 },
            reduce: function(obj,prev) { prev.csum += obj.c; },
            initial: { csum: 0 }
            });

参数说明:
1)key:要分组的列。本例中为a和b。
2)cond:分组条件。可以理解为where条件内容,本例中为active=1。
3)reduce: 分组计算的方法。本例中为sum(c)。
4)initial:分组计算的初始值。本例中指csum的值从0开始计算。

相关文章
|
NoSQL 测试技术 MongoDB
微服务——MongoDB实战演练——根据上级ID查询文章评论的分页列表
本节介绍如何根据上级ID查询文章评论的分页列表,主要包括以下内容:(1)在CommentRepository中新增`findByParentid`方法,用于按父ID查询子评论分页列表;(2)在CommentService中新增`findCommentListPageByParentid`方法,封装分页逻辑;(3)提供JUnit测试用例,验证功能正确性;(4)使用Compass插入测试数据并执行测试,展示查询结果。通过这些步骤,实现对评论的高效分页查询。
258 0
|
10月前
|
存储 JSON NoSQL
查询 MongoDB--SPL 轻量级多源混算实践 4
SPL 支持多种数据源连接,包括 MongoDB 等 NoSQL 数据库。通过外部库形式提供驱动,灵活扩展,可实现实时数据计算与混合分析。
|
运维 监控 NoSQL
客户说|莉莉丝《剑与远征:启程》引入阿里云MongoDB,助力游戏高效开发
客户说|莉莉丝《剑与远征:启程》引入阿里云MongoDB,助力游戏高效开发
761 1
|
SQL NoSQL Java
Java使用sql查询mongodb
通过MongoDB Atlas Data Lake或Apache Drill,可以在Java中使用SQL语法查询MongoDB数据。这两种方法都需要适当的配置和依赖库的支持。希望本文提供的示例和说明能够帮助开发者实现这一目标。
674 17
|
SQL NoSQL Java
Java使用sql查询mongodb
通过使用 MongoDB Connector for BI 和 JDBC,开发者可以在 Java 中使用 SQL 语法查询 MongoDB 数据库。这种方法对于熟悉 SQL 的团队非常有帮助,能够快速实现对 MongoDB 数据的操作。同时,也需要注意到这种方法的性能和功能限制,根据具体应用场景进行选择和优化。
662 9
|
存储 NoSQL Cloud Native
MongoDB云原生化:为企业开发注入高效动力
MongoDB云原生化为企业开发注入高效动力,分为三部分:1. 介绍阿里云和MongoDB的服务;2. 阿里云MongoDB解决自建模型痛点的功能,包括隔离性、海量数据处理、弹性能力及运维操作优化;3. 客户案例展示。通过云原生架构,MongoDB实现了灵活的扩展、高效的备份恢复和快速的回档能力,显著提升了企业的业务迭代速度和数据管理效率。典型客户如吉比特、莉莉丝、掌阅等受益于这些功能,实现了更稳定和高效的数据库服务。
|
存储 NoSQL MongoDB
MongoDB 查询分析
10月更文挑战第21天
199 1
|
NoSQL MongoDB 索引
MongoDB 覆盖索引查询
10月更文挑战第21天
197 1
|
NoSQL Java MongoDB
MongoDB $type 操作符
10月更文挑战第16天
263 2
|
NoSQL JavaScript 前端开发
MongoDB 条件操作符
10月更文挑战第15天
248 1

推荐镜像

更多