《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
相关文章
|
2月前
|
存储 NoSQL MongoDB
掌握MongoDB索引优化策略:提升查询效率的关键
在数据库性能调优中,索引是提升查询效率的利器。本文将带你深入了解MongoDB索引的内部工作原理,探讨索引对查询性能的影响,并通过实际案例指导如何针对不同的查询模式建立有效的索引。不仅将涵盖单一字段索引,还会探讨复合索引的使用,以及如何通过分析查询模式和执行计划来优化索引,最终实现查询性能的最大化。
|
4天前
|
SQL NoSQL Java
Java使用sql查询mongodb
通过使用 MongoDB Connector for BI 和 JDBC,开发者可以在 Java 中使用 SQL 语法查询 MongoDB 数据库。这种方法对于熟悉 SQL 的团队非常有帮助,能够快速实现对 MongoDB 数据的操作。同时,也需要注意到这种方法的性能和功能限制,根据具体应用场景进行选择和优化。
27 9
|
3天前
|
存储 NoSQL Cloud Native
MongoDB云原生化:为企业开发注入高效动力
MongoDB云原生化为企业开发注入高效动力,分为三部分:1. 介绍阿里云和MongoDB的服务;2. 阿里云MongoDB解决自建模型痛点的功能,包括隔离性、海量数据处理、弹性能力及运维操作优化;3. 客户案例展示。通过云原生架构,MongoDB实现了灵活的扩展、高效的备份恢复和快速的回档能力,显著提升了企业的业务迭代速度和数据管理效率。典型客户如吉比特、莉莉丝、掌阅等受益于这些功能,实现了更稳定和高效的数据库服务。
|
2月前
|
存储 NoSQL MongoDB
MongoDB 查询分析
10月更文挑战第21天
22 1
|
2月前
|
NoSQL MongoDB 索引
MongoDB 覆盖索引查询
10月更文挑战第21天
37 1
|
2月前
|
NoSQL Java MongoDB
MongoDB $type 操作符
10月更文挑战第16天
28 2
|
2月前
|
NoSQL JavaScript 前端开发
MongoDB 条件操作符
10月更文挑战第15天
30 1
|
2月前
|
SQL NoSQL MongoDB
MongoDB 查询文档
10月更文挑战第15天
38 1
|
2月前
|
存储 人工智能 NoSQL
使用 MongoDB 构建 AI:Gradient Accelerator Block 如何在几秒钟内让您从零开发 AI
借助 MongoDB,开发者可以存储任何结构的数据,然后使用单一查询 API 和驱动程序将这些数据用于 OLTP、文本搜索和向量搜索处理。
|
2月前
|
人工智能 NoSQL 机器人
MongoDB Atlas与YoMio.AI近乎完美适配:推理更快速、查询更灵活、场景更丰富
随着MongoDB的新发布和革新,YoMio.AI的“闪电式发展”值得期待。