mongodb 高级查询详解

MongoDB:管道操作

使用聚合框架可以对集合中的文档进行变换和组合。基本上,可以用多个构件创建一个管道(pipeline),用于对一连串的文档进行处理。这些构件包括筛选(filter)、投射(projecting)、分组(grouping)、排序(sorting)、限制(limiting)和跳过(skipping)。

例如,有一个保存书籍信息的集合,你想知道投票数量最多的书籍。可以按照如下步骤创建管道:

  • 将每个书籍信息中的书名和投票投射出来{"$project":{"title":1,"vote_num":1}}
  • 统计每个书名所有的投票数(书名可能重复){"$group":{"_id":"$title","vote_num":{"$sum":"$vote_num"}}}
  • 按照投票数降序排列{"$sort":{"vote_num":-1}}
  • 将返回结果限制为前5个{"$limit":5}
db.book_info.aggregate({"$project":{"title":1,"vote_num":1}},{"$group":{"_id":"$title","vote_num":{"$sum":"$vote_num"}}},{"$sort":{"vote_num":-1}},{"$limit":5})

结果

{ "_id" : "小王子", "vote_num" : 265438 }
{ "_id" : "活着", "vote_num" : 263733 }
{ "_id" : "追风筝的人", "vote_num" : 253532 }
{ "_id" : "白夜行", "vote_num" : 232564 }
{ "_id" : "梦里花落知多少", "vote_num" : 204792 }

$match

$match用于对文档集合记性筛选,之后就可以在筛选得到的文档子集上做聚合。

db.book_info.aggregate({"$match":{"title":"小王子"}},{"$project":{"title":1,"vote_num":1}})

结果

{ "_id" : ObjectId("58d3972be13823416ede764c"), "title" : "小王子", "vote_num" : 210926 }
{ "_id" : ObjectId("58d397c6e13823416ede823c"), "title" : "小王子", "vote_num" : 10273 }
{ "_id" : ObjectId("58d398a6e13823416ede930a"), "title" : "小王子", "vote_num" : 3748 }
...

match可以使用所有常规的查询操作符("

gt”、”lt"、"

in”等)

db.book_info.aggregate({"$match":{"title":"小王子","vote_num":{"$lt":100}}},{"$project":{"title":1,"vote_num":1}})

结果

{ "_id" : ObjectId("58d39d27e13823416edeec07"), "title" : "小王子", "vote_num" : 65 }
{ "_id" : ObjectId("58d39e33e13823416edf01e4"), "title" : "小王子", "vote_num" : 91 }
{ "_id" : ObjectId("58d39f2fe13823416edf1670"), "title" : "小王子", "vote_num" : 93 }
...

$project

使用$project操作,可以从子文档中提取字段,可以重命名字段,还可以再这些字段上进行一些有意思的操作。

选择想要的字段

db.book_info.aggregate({"$project":{"title":1,"vote_num":1}})

结果

{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "vote_num" : 38478 }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "vote_num" : 598 }
{ "_id" : ObjectId("58d39725e13823416ede75f2"), "title" : "酝酿之道", "vote_num" : 32 }
...

重命名字段。这里的$vote_num语法是为了在聚合框架中引用vote_num字段

db.book_info.aggregate({"$project":{"title":1,"vote_num_rename":"$vote_num"}})

结果

{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "vote_num_rename" : 38478 }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "vote_num_rename" : 598 }
{ "_id" : ObjectId("58d39725e13823416ede75f2"), "title" : "酝酿之道", "vote_num_rename" : 32 }

$project还支持如下表达式

数学表达式

  • “$add”:[expr1[,expr2,…,exprN]] 接受一个或多个表达式作为参数,将这些表达式相加
  • “$subtract”:[expr1,expr2] 接受两个表达式作为参数,用第一个表达式减去第二个表达式作为结果
  • “$multiply”:[expr1[,expr2,…,exprN]] 接受一个或多个表达式,并且将他们相乘
  • “$divide”:[expr1,expr2] 接受两个表达式,用第一个表达式除以第二个表达式的商作为结果
  • “$mod”:[expr1,expr2] 接受两个表达式,将第一个表达式除以第二个表达式得到的余数作为结果

日期表达式(只能对日期类型的字段进行日期操作,不能对数值类型字段做日期操作)

  • $year
  • $month
  • $week
  • $dayOfMonth
  • $dayOfWeek
  • $dayOfYear
  • $hour

字符串表达式

  • “$substr”:[expr,startOffset,numToReturn] 截取字符串的子串,从startOffset字节开始,一共numToReturn个字节
  • “$concat”:[expr1[,expr2,…,exprN]] 将给定的表达式(或字符串)连接在一起作为返回结果
  • “$toLower”:expr expr必须是字符串,返回expr的小写形式
  • “$toUpper”:expr 返回expr的大写形式

逻辑表达式

  • “$cmp”:[expr1,expr2] 比较expr1和expr2,如果相等返回0,expr1

$group

$group操作可以将文档依据特定字段的不同值进行分组。

db.book_info.aggregate({"$project":{"title":1,"vote_num":1}},{"$group":{"_id":"$title","count":{"$sum":1}}})

结果

{ "_id" : "jQuery实战", "count" : 3 }
{ "_id" : "Casanova Was a Book Lover", "count" : 1 }
{ "_id" : "Chris Killip", "count" : 1 }
...

算数操作符

  • “$sum”:value 求和
  • “$avg”:value 求平均值

极值操作符

  • “$max”:expr 返回组内的最大值
  • “$min”:expr 返回组内的最小值
  • “$first”:expr 返回分组的第一个值
  • “$last”:expr 返回分组的最后一个值

数组操作符

  • “$addToSet”:expr 如果当前数组不包含expr,则将其添加到数组中,在返回结果集中,每个元素最多出现1次,而且元素的顺序是不确定的
  • “$push”:expr 不管expr是什么值,都将它添加到数组中,返回包含所有值的数组

$unwind

拆分可以将数组中的每一个值拆分成单独的文档。例如

> db.book_info.find({},{"title":1,"tags":1})
{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "tags" : [ "茨威格", "一个陌生女人的来信", "外国文学", "爱情", "小说", "奥地利", "经典", "文学" ] }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "tags" : [ "犯罪小说", "推理", "悬疑", "尤?奈斯博", "小说", "外国文学", "北欧", "人性" ] }
...

db.book_info.aggregate({"$project":{"title":1,"tags":1}},{"$unwind":"$tags"})
{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "tags" : "茨威格" }
{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "tags" : "一个陌生女人的来信" }
{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "tags" : "外国文学" }
{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "tags" : "爱情" }
{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "tags" : "小说" }
{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "tags" : "奥地利" }
{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "tags" : "经典" }
{ "_id" : ObjectId("58d39725e13823416ede75f0"), "title" : "一个陌生女人的来信", "tags" : "文学" }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "tags" : "犯罪小说" }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "tags" : "推理" }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "tags" : "悬疑" }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "tags" : "尤·奈斯博" }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "tags" : "小说" }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "tags" : "外国文学" }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "tags" : "北欧" }
{ "_id" : ObjectId("58d39725e13823416ede75f1"), "title" : "猎豹", "tags" : "人性" }
...

$sort

可以根据任何字段(或者多个字段)进行排序,与在普通查询中的语法是相同的。如果要对大量的文档进行排序,强烈建议在管道的第一阶段进行排序,这时的排序操作可以使用索引。否则,排序过程就会比较慢,而且会占用大量内存。

1是升序,-1是降序

db.book_info.aggregate({"$project":{"title":1,"vote_num":1}},{"$sort":{"vote_num":-1}})

结果

{ "_id" : ObjectId("58d39726e13823416ede75ff"), "title" : "追风筝的人", "vote_num" : 247079 }
{ "_id" : ObjectId("58d3972be13823416ede764c"), "title" : "小王子", "vote_num" : 210926 }
{ "_id" : ObjectId("58d3972ae13823416ede7641"), "title" : "围城", "vote_num" : 179228 }
{ "_id" : ObjectId("58d3972de13823416ede766a"), "title" : "白夜行", "vote_num" : 172310 }
{ "_id" : ObjectId("58d39725e13823416ede75f3"), "title" : "解忧杂货店", "vote_num" : 166469 }
...

$limit

$limit接受一个数字n,返回结果集中的前n个文档

db.book_info.aggregate({"$limit":5})

$skip

$skip接受一个数字n,表示丢弃结果集中的前n个文档。如果需要跳过大量的数据,那么这个操作符的效率会比较低。

db.book_info.aggregate({"$skip":5})

原文地址:https://www.cnblogs.com/wangyuxing/p/9923206.html

时间: 2024-10-07 18:40:19

mongodb 高级查询详解的相关文章

MongoDB状态查询详解:db.serverStatus()

基本信息 spock:PRIMARY>db.serverStatus() { "host" :"h6.corp.yongche.org",   //主机名 "version" :"2.6.2",            //mongodb版本 "process" :"mongod",        //mongodb进程,主要有mongod和mongos(分片集群中)两种 "

mysql简单的单表查询详解

mysql简单的单表查询详解 MySQL的查询操作: 单表查询:简单查询 多表查询:连续查询 联合查询: 选择和投影: 投影:挑选要显示的字段 选择:挑选符合条件的行 投影:SELECT 字段1, 字段2, ... FROM tb_name;  SELECT * FROM tb_name; 选择:SELECT 字段1, ... FROM tb_name WHERE 子句; 布尔条件表达式 mysql> CREATE TABLE students (SID INT UNSIGNED AUTO_IN

使用VS2010编译MongoDB C++驱动详解

最近为了解决IM消息记录的高速度写入.多文档类型支持的需求,决定使用MongoDB来解决. 考虑到MongoDB对VS版本要求较高,与我现有的VS版本不兼容,在leveldb.ssdb.redis.hbase等NoSQL中转了一圈,最后还是选择了MongoDB,应了那句话:没有最好的,只有最合适的. MongoDB由于使用了C++的新特性,官方建议使用VS2013来编译,最低要求VS2010. MongoDB C++驱动编译过程较为复杂,官方也没有提供编译好的驱动包,网上的资料编译版本都比较老了

MySQL_05-Select查询详解

SQL查询详解 1.Orderby a) Order by 字段 asc | desc b) 允许多字段排序: 先按第一个字段排序,如果不能区分,再使用第二个字段排序:以此类推 2.Limit(限制获得的记录数量) a) 语法: limit offset, row_count  (offset:偏移量,下标从0开始:row_count:总记录数).例如:limit 2,3 表示从第二条开始,取三条(即第2条到第4条记录) 3.Distinct a) 去除重复记录. b) 语法: select d

sql语句联合查询详解

sql语句联合查询详解 2011-03-01 18:58:22|  分类: mysql|举报|字号 订阅 例子: person表和user表没有约束person表: user表: 有以下几种关联 1.UNION 格式:查询语句 UNION [ALL] 查询语句 [UNION [ALL] 查询语句][…n] 说明:ALL选项表示将所有行合并到结果集合中.不指定该项时,被联合查询结果集合中的重复行将只保留一行. 在包括多个查询的UNION语句中,其执行顺序是自左至右,使用括号可以改变这一执行顺序.例

Python中的高级数据结构详解

这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考下 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据结构,分别是List.Tuple.Dictionary以及Set.大部分的应用程序不需要其他类型的数据结构,但若是真需要也有很多高级数据结构可供选择

ThinkPHP视图查询详解

ThinkPHP视图查询详解 参考http://www.jb51.net/article/51674.htm 这篇文章主要介绍了ThinkPHP视图查询,需要的朋友可以参考下 ThinkPHP提供的视图查询应用功能十分强大,用户利用视图查询功能可以将多个数据表的字段内容按需要进行指定和筛选,组织成一个基于这些数据表的视图模型,然后就可以通过该模型直接进行多表联合查询,非常方便和简单. 例如在项目中,我们定义有三个表: user          用户基础表,user_info   用户详细信息表

mongoDB 高级查询语法

http://www.cnblogs.com/ITAres/articles/2084794.html本文参考自官方的手册:http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ConditionalOperators%3A%3C%2C%3C%3D%2C%3E%2C%3E%3D 1 ) . 大于,小于,大于或等于,小于或等于 $gt:大于 $lt:小于 $gte:大于或等于 $lte:小于或等于 例子: db.c

SQL常规查询详解

一.交叉连接(cross join) 交叉连接(cross join):有两种,显式的和隐式的,不带on子句,返回的是两表的乘积,也叫笛卡尔积. 例如:下面的语句1和语句2的结果是相同的. 语句1:隐式的交叉连接,没有cross join. select o.id, o.order_number, c.id, c.name from orders o , customers c where o.id=1; 语句2:显式的交叉连接,使用cross join. select o.id,o.order