MongoDB的union操作是什么。Union类似于SQL中的UNION ALL,可以将多个查询结果合并,并去除重复文档;
使用ThinkPHP 5或更高版本,通常会通过MongoDB的驱动或者第三方库来操作。不过,标准的MongoDB驱动可能不直接支持union操作,所以需要构造多个查询,分别执行然后合并结果
检查MongoDB版本:确保使用的MongoDB版本支持union操作(MongoDB 3.6+)。
构造子查询:每个子查询对应一个聚合管道,使用match、project等阶段筛选和投影需要的字段。
执行union操作:使用MongoDB的$union聚合阶段将多个子查询的结果合并。
在Think PHP中实现:通过MongoDB的客户端执行聚合管道,包含$union阶段。
安装 MongoDB 扩展:确保 PHP 已安装 mongodb 扩展。
配置 ThinkPHP 数据库连接
'_mongo' => [
// 数据库类型
'type' => '\think\mongo\Connection',
// 设置查询类 'query' => '\think\mongo\Query',
// 服务器地址 'hostname' => MyEnv::get('DATABASE.all_mongo_hostname'),
// 集合名 'database' => MyEnv::get('DATABASE.all_mongo_database'),
// 用户名 'username' => MyEnv::get('DATABASE.all_mongo_username'),
// 密码 'password' => MyEnv::get('DATABASE.all_mongo_password'),
// 端口 'hostport' => MyEnv::get('DATABASE.all_mongo_hostport', '8365'),
// 强制把_id转换为id 'pk_convert_id' => true, 'params'=> ['replicaSet' => 'replica'],
],
single_chat当前的聊天集合是按照年月进行聚合存储的 例如:single_chat202412,single_chat202501,single_chat202502,查询多个集合的数据的时候可以采用如下实现方式:
具体的实现代码
//获取数据
php">$months = self::getMonths($data['over_time'], $data['begin_time']);
$password = config('database._mongo.password'); //密码
$hostname = config('app.mongoUrl');
$url = "mongodb://user123456:" . $password . "@" . $hostname;
$mongo = new Manager($url);
$databaseName = 'single_chat';
$months = array_reverse($months);
$collection = new Collection($mongo, $databaseName, $months[0] . 'signChat');
$pipeline = [];
$matchOptions['chatName'] = $aggregate_name;
$matchOptions['action'] = ['$ne' => 'action'];
$matchOptions['msgtype'] = 'text';
$match = ['$match' => $matchOptions
];
$num=count($months);
for ($i = 1; $i < $num; $i++) {$unionWith = ['$unionWith' => ['coll' => $months[$i] . 'signChat', // 合并的集合名称'pipeline' => [$match]]];$pipeline[] = $unionWith;$pipelineCommon[] = $unionWith;
}
$match = ['$match' => $matchOptions];
$sort = ['$sort' => ['seq' => -1 // -1 表示降序排序,1 表示升序排序]
];
$count = ['$count' => 'total' // 计算合并后的总文档数
];
$pipelineCommon[] = $sort;
$pipelineCommon[] = $match;
$pipeline[] = $match;
$page = (int)$data['page'];
$pageSize = (int)$data['pageSize'];
$skip = ['$skip' => ($page - 1) * $pageSize// 跳过指定数量的文档,用于分页
];
$limit = ['$limit' => $pageSize // 限制返回的文档数量,即每页的大小
];
$pipelineCommon[] = $skip;
$pipelineCommon[] = $limit;
$pipeline[] = $count;
$results = $collection->aggregate($pipeline)->toArray();
if (isset($results[0]['total'])) {$totalNum = $results[0]['total'];$chatListMongo = $collection->aggregate($pipelineCommon)->toArray();
} else {$totalNum = 0;$chatListMongo = [];
}
$return['total'] = $totalNum;
$return['per_page'] = $data['pageSize'];
$return['current_page'] = $data['page'];;
$return['last_page'] = ceil($return['total'] / $return['per_page']);
以上就是全部的实现方式了,如果能帮到各位,帮个点个赞~