当前位置:首页 > PHP > MongoDB驱动聚合查询aggregate在分组分页排序后出现的数据混乱问题

宝塔服务器面板,一键全能部署及管理,送你3188元礼包,点我领取

MongoDB驱动聚合查询aggregate在分组分页排序后出现的数据混乱问题

原创 2020-11-06 PHP 1599
分享给朋友:

u=60481258,2906075580&fm=26&gp=0.jpg

最近在获取MongoDB数据时需要把重复的数据分组来排序,语言版本:PHP7

直接上代码

$param = [
    'aggregate' => '表名',
    'pipeline'  => [
        // 搜索条件
        ['$match' => ['status' => 1]],
        // 根据重复的title来group分组 max_sort=>获取最大的排序值
        ['$group' => ['_id' => '$title', 'count' => ['$sum' => 1], 'max_sort' => ['$max' => '$sort']]],
        // 根据分组的最大值条件降序
        ['$sort' => ['max_sort' => -1]]
    ],
    // 高版本需要带上这个值
    'cursor'    => new \stdClass()
];
$mongodb = new MaMongoDB\Driver\Managerager('mongodb://localhost:27017/', []);
$command = new MongoDB\Driver\Command($param);
$result  = $mongodb->executeCommand('数据库', $command);
$res   = $result->toArray();

一切都是按照预想的结果,但是出来的结果太多了,实际项目中大多数需要分页效果,这时候加上skip,limit条件进去

    'pipeline'  => [
        // 搜索条件
        ['$match' => ['status' => 1]],
        // 根据重复的title来group分组 max_sort=>获取最大的排序值
        ['$group' => ['_id' => '$title', 'count' => ['$sum' => 1], 'max_sort' => ['$max' => '$sort']]],
        ['$skip'  => ($page - 1) * $limit],
        ['$limit' => (int)$limit,
        // 根据分组的最大值条件降序
        ['$sort'  => ['max_sort' => -1]]
    ],

跑下代码之后发现出来的结果倒是问题,但是排序混乱了。。。

why?在没有解决这个问题之前,可谓是翻遍了Google、Baidu、CSDN等所有能查的资源网站,都无从解决下手。最后无奈,只能顶着网速和过了18级的英语水平去看官网的文档了。

在MongoDB游标方法中,例如限额,排序,跳过可以以任何顺序应用=>顺序无关紧要。 find()返回一个游标,在其上应用了修改。排序总是在限制之前完成,跳过也要在限制之前完成。因此换句话说,顺序是:排序->跳过->限制

聚合框架不会返回数据库游标。而是返回带有汇总结果的 document 。它的工作原理是在管道的每个步骤中产生中间结果,因此操作的顺序确实很重要。

重点来了,聚合查询不会返回数据游标,所以排序很重要。按照MongoDB官方的推荐写法

db.test.find().sort({"age":1}).limit(2);

也就是说正常的顺序是sort->skip->limit,这时候把上面的语句换下顺序后

    'pipeline'  => [
        // 搜索条件
        ['$match' => ['status' => 1]],
        // 根据重复的title来group分组 max_sort=>获取最大的排序值
        ['$group' => ['_id' => '$title', 'count' => ['$sum' => 1], 'max_sort' => ['$max' => '$sort']]],
        // 根据分组的最大值条件降序
        ['$sort'  => ['max_sort' => -1]],
        ['$skip'  => ($page - 1) * $limit],
        ['$limit' => (int)$limit,
    ],

再跑下代码,分组分页正常,排序也是按照sort里面的条件排了。可能很多小伙伴遵循了sort->skip->limit这种顺序的写法没有出现过异常,但是对于平时不是那么严谨的小伙伴来说,比如我,可能就会在这种问题上卡很久,谁会想到一个数组的排序会多数据结果产生那么大的影响。

记录下此次教训~~~

声明:版权所有,违者必究 | 如未注明,均为原创 | 本网站采用 BY-NC-SA 协议进行授权

转载:转载请注明原文链接,违者必究 - :https://www.wolfcode.net/info/208/

分享给朋友:

相关文章

EasyAdmin8 - PHP8.0常用框架快速后台管理系统

EasyAdmin8 开源快速开发后台,ThinKPHP 、 Laravel、webman 均覆盖

webman-blog 基于 webman 开源博客程序

webman-blog,一个基于 webman 的简单自适应个人博客程序,带后台。

webman自定义进程

1、新建文件 process/Rpc.php 编写rpc进程<?php namespace process; use Workerman\Connection\TcpConnection; class Rpc {    &n

在PHP7+下监控Memcached服务、性能、扇区等信息

PHPMemcachedAdmin:一款网页可视化的Memcached工具

Swoole的PHP协程开发框架 imi 集成ThinkPHP模板引擎 think-template

在 imi 框架根目录中执行composer require topthink/think-template安装好模板引擎后,找到路径\vendor\topthink\think-template\src\Template.php找到 fetch() 渲染模板文件的方法,将最后一

PHP7下MongoDB自增或自减一个字段的值

findAndModify属于原子操作模型数据,所谓原子操作就是要么这个文档保存到Mongodb,要么没有保存到Mongodb,不会出现查询到的文档没有保存完整的情况。

PHP的面向对象解析

早期编程由于受电脑硬件限制,程序都是追求效率,而忽略可理解性,扩充性,随着硬件技术的发展,编程越来越重视多人开发,程序员越来越重视程序的可靠性,可扩展性,可维护性,所以刺激了程序语言的发展

ThinkPHP6.0使用EasyTask常驻内存多进程任务管理

PHP常驻内存的多进程任务管理器Composer包。以进程管理为出发点,同时也支持为每个进程设置定时执行功能,您可以用它来完成需要重复运行的任务(如订单超时自动取消,短信邮件异步推送,队列/消费者/频道订阅者等等),甚至处理计划任务。

PHP8新特性盘点

PHP 8.0.0 已经正式发布了,这个对于PHPer无疑是一个令人振奋的消息。它包含了很多新功能与优化项, 包括命名参数、联合类型、注解、构造器属性提升、match表达式、nullsafe运算符、JIT,并改进了类型系统、错误处理、语法一致性。

PHP8新特性系列:构造器属性提升使用及注意事项

本篇主要说下PHP8构造器属性提升的用法,这个特性对于一些需要在构造器中设置或初始化一些类属性的时候非常有用(包括public、protected和private),比如在PHP7中你可以这样定义一个类的属性,然后在构造方法中传值。class Point {  &nb