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

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: 本节书摘来自华章社区《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开始计算。

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
3月前
|
JSON NoSQL MongoDB
Rockmongo详解:高效管理MongoDB的图形化利器
Rockmongo详解:高效管理MongoDB的图形化利器
|
3月前
|
NoSQL 定位技术 MongoDB
解锁MongoDB索引的秘密:优化查询效率与应对限制的策略
解锁MongoDB索引的秘密:优化查询效率与应对限制的策略
|
3天前
|
SQL NoSQL JavaScript
04 MongoDB各种查询操作 以及聚合操作总结
文章全面总结了MongoDB中的查询操作及聚合操作,包括基本查询、条件筛选、排序以及聚合管道的使用方法和实例。
15 0
|
1月前
|
JSON NoSQL MongoDB
MongoDB Schema设计实战指南:优化数据结构,提升查询性能与数据一致性
【8月更文挑战第24天】MongoDB是一款领先的NoSQL数据库,其灵活的文档模型突破了传统关系型数据库的限制。它允许自定义数据结构,适应多样化的数据需求。设计MongoDB的Schema时需考虑数据访问模式、一致性需求及性能因素。设计原则强调简洁性、查询优化与合理使用索引。例如,在构建博客系统时,可以通过精心设计文章和用户的集合结构来提高查询效率并确保数据一致性。正确设计能够充分发挥MongoDB的优势,实现高效的数据管理。
40 3
|
1月前
|
存储 NoSQL MongoDB
【掌握MongoDB】轻松精通MongoDB查询,从基础到高级一网打尽!
【8月更文挑战第24天】在数据驱动的时代,数据库的性能与灵活性对企业至关重要。MongoDB作为一种高性能、无模式的文档数据库,为开发者提供了灵活的数据存储方案。尤其在处理半结构化或多变数据时展现出强大优势。本文重点介绍MongoDB中的查询操作,包括基本查询、条件查询、复杂查询以及字段选择、排序和限制等功能。通过掌握这些基本查询技巧,开发者能够有效从MongoDB中检索数据,支持复杂的业务逻辑。
49 1
|
1月前
|
监控 NoSQL MongoDB
mongodb查询100万数据如何查询快速
综上,提高MongoDB百万级数据的查询性能需要综合多项技术,并在实际应用中不断调优和实践。理解数据的特征,合理设计索引,优化查询语句,在数据访问、管理上遵循最佳的实践,这样才能有效地管理和查询大规模的数据集合。
120 1
|
28天前
|
C# 微服务 Windows
模块化革命:揭秘WPF与微服务架构的完美融合——从单一职责原则到事件聚合器模式,构建高度解耦与可扩展的应用程序
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中借鉴微服务架构思想,实现模块化设计。通过将WPF应用分解为独立的功能模块,并利用事件聚合器实现模块间解耦通信,可以有效提升开发效率和系统可维护性。文中还提供了具体示例代码,展示了如何使用事件聚合器进行模块间通信,以及如何利用依赖注入进一步提高模块解耦程度。此方法不仅有助于简化复杂度,还能使应用更加灵活易扩展。
58 0
|
28天前
|
安全 C# 数据安全/隐私保护
WPF安全加固全攻略:从数据绑定到网络通信,多维度防范让你的应用固若金汤,抵御各类攻击
【8月更文挑战第31天】安全性是WPF应用程序开发中不可或缺的一部分。本文从技术角度探讨了WPF应用面临的多种安全威胁及防护措施。通过严格验证绑定数据、限制资源加载来源、实施基于角色的权限管理和使用加密技术保障网络通信安全,可有效提升应用安全性,增强用户信任。例如,使用HTML编码防止XSS攻击、检查资源签名确保其可信度、定义安全策略限制文件访问权限,以及采用HTTPS和加密算法保护数据传输。这些措施有助于全面保障WPF应用的安全性。
34 0
|
1月前
|
开发框架 NoSQL 关系型数据库
基于SqlSugar的开发框架循序渐进介绍(27)-- 基于MongoDB的数据库操作整合
基于SqlSugar的开发框架循序渐进介绍(27)-- 基于MongoDB的数据库操作整合
|
2月前
|
NoSQL 关系型数据库 MySQL
优化MongoDB查询
【7月更文挑战第4天】
36 0