MongoDB查询区分、排序、限制和偏移
Posted
技术标签:
【中文标题】MongoDB查询区分、排序、限制和偏移【英文标题】:MongoDB query to distinct, sort, limit and offset 【发布时间】:2013-01-10 21:34:45 【问题描述】:我正在寻找与以下类似的 Mongo:
select distinct event_type_id from events
order by created_at desc
limit 10,20
Event Mongo文档如下:
_id: BSON(), event_type_id: 1, created_at: Date(), other_data:
【问题讨论】:
【参考方案1】:您可以在新的 mongo 版本上使用 Aggregation Framework。以下是开始的示例:
db.events.aggregate([
$sort:"created_at":-1,
$project:"event_type_id":1,
$group:"_id":"$event_type_id",
$skip:10,
$limit:20
])
感谢@JoachimIsaksson,这是另一种方法
db.events.aggregate([
$group:"_id":"$event_type_id", "created_at":$max:"$created_at",
$sort:"created_at":-1,
$skip:10,
$limit:20,
$project:"event_type_id":1
])
【讨论】:
有什么方法可以做不同的吗? 很抱歉,正在努力学习...... :) 你真的可以一个接一个地分组并保持顺序吗? 我一直在想一些事情;$group:_id:"$event_type_id", ord: $max:"$created_at",$sort:"ord":-1,$project:"event_type_id":1,$skip:10,$limit:20
但我在这里免费发短信,没有任何东西可以尝试:)
@JoachimIsaksson SQL DISTINCT 命令依赖于数据库,但在大多数 SQL 数据库中,它是一个 $group
,使用文档每个字段的 $min
或 $max
。 DISTINCT 查询有一个巨大的缺陷,但你无法确定,这取决于 db 实现。
@JoachimIsaksson 是的,你可以在 $group 中进行排序,检查我的编辑【参考方案2】:
您始终可以通过 v2.2 中引入的聚合框架来做到这一点:
db.col.aggregate(
$group: _id: "$event_type_id", created_at: "$created_at",
($sort: "$created_at":-1
);
类似的东西会分组,这实际上与 distinct 相同,所有 event_type_id
值并按 created_at
降序排序。
这应该没问题,但请注意,目前它的输出限制 (atm) 为 16meg,因此如果您要输出一个巨大的文档,您可能会觉得很困难。
编辑
为了提高性能,您实际上可以先使用索引进行排序,然后再使用$group
:
db.col.aggregate(
$sort: "$created_at":-1 ,
$group: _id: "$event_type_id", created_at: $first: "$created_at"
);
这使用$first
(http://docs.mongodb.org/manual/reference/aggregation/first/) 运算符来获取该组中该字段的第一个值。您也可以使用$last
运算符,这些当然会转换为普通的$min
和$max
,但用于排序集。
【讨论】:
您好,感谢$first
示例。如果我想在组之后添加过滤器,例如,如果我只想保留将 type
设置为 true
的项目,将 type: $first: '$type'
添加到 $group
然后添加新区块 $match: type: true
。这可以吗?或者有更好的方法吗?
@Matteo no 在这种情况下,您将使用 $max ,因为您不能肯定地说排序集是您想要的 $first 或 $last ,因此您将在此实际获得该字段的 $max案例
$max 是什么?对于布尔字段,它没有任何意义。我的意思是,我的代码与您的示例非常相似。我按日期(“created_time”)排序,然后我想用另一个字段过滤结果,提取集合中的第一个(连同日期)。我这样做的方式似乎有效,但如果它是正确的,我就不会。
@Matteo 布尔字段转换为 1 和 0,1 表示真,0 表示假。 $max 将始终返回 true,但是,如果您排序的第一个分组日期的类型为 false,则 $first 可能会返回 false,但只有当日期可以具有不同的布尔值并且您希望优先于 true 时才会出现这种情况, 不是第一个排序的
@Matteo 归根结底,我可能对您的数据和场景了解得不够多,无法说明哪个是最好的,您可能会发现最好提出一个带有更详细解释的问题,然后可以回答。【参考方案3】:
我认为您不能在 mongo 中将限制和跳过命令与不同的查询结合使用。下面的代码将返回相当于下面的 sql 语句:
select distinct event_type_id from events
order by created_at desc
db.events.distinct( 'event_type_id', , createdAt: -1 )
检索结果后,您可以根据需要从中提取子集。您也可以查看以下帖子:How to use Distinct, Sort, limit with mongodb
显然这是mongo社区的公开票,你也可以检查问题,看起来他们暂时不会实现limit和distinct的组合https://jira.mongodb.org/browse/SERVER-2130
【讨论】:
我只能找到2 parameters to distinct 记录,你在哪里找到第三个? :) javascript 允许您调用具有任意数量参数的方法,但这不起作用。 但是它从 shell 给出了正确的结果,这怎么会发生? @cubbuk 它可能会按插入顺序返回结果,而该顺序恰好是您所期望的?通过升序排序是否可以反转顺序? 这就是我在更改排序查询时以降序或升序得到的结果。以上是关于MongoDB查询区分、排序、限制和偏移的主要内容,如果未能解决你的问题,请参考以下文章
Elasticsearch+Mongo亿级别数据导入及查询实践