php实现附近的人
使用MySQL空间函数实现
MySQL的ST_Distance_Sphere函数可以计算两个地理坐标点之间的距离(单位:米)。需要确保MySQL版本在5.7以上且表中包含空间数据类型字段。
创建包含地理位置字段的表:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
location POINT NOT NULL,
SPATIAL INDEX(location)
);
插入带地理坐标的数据:
INSERT INTO users (name, location) VALUES
('用户1', ST_PointFromText('POINT(116.404 39.915)')),
('用户2', ST_PointFromText('POINT(116.405 39.916)'));
查询附近5公里范围内的人:
$lat = 39.915; // 当前纬度
$lng = 116.404; // 当前经度
$distance = 5000; // 5公里范围
$query = "SELECT id, name,
ST_Distance_Sphere(location, ST_PointFromText('POINT($lng $lat)')) AS distance
FROM users
WHERE ST_Distance_Sphere(location, ST_PointFromText('POINT($lng $lat)')) <= $distance
ORDER BY distance";
使用Redis GEO命令实现
Redis的GEO功能适合高性能场景,使用GEOADD添加位置,GEORADIUS查询附近的人。
添加用户位置到Redis:

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 添加用户坐标
$redis->geoAdd('users:location', 116.404, 39.915, 'user1');
$redis->geoAdd('users:location', 116.405, 39.916, 'user2');
查询附近5公里的人:
$result = $redis->geoRadius('users:location', 116.404, 39.915, 5, 'km', [
'WITHDIST',
'ASC'
]);
使用MongoDB地理空间查询
MongoDB支持2dsphere索引进行地理空间查询,适合文档型数据结构。
创建位置索引:

$collection->createIndex(['location' => '2dsphere']);
插入带位置的数据:
$collection->insertOne([
'name' => '用户1',
'location' => [
'type' => 'Point',
'coordinates' => [116.404, 39.915]
]
]);
查询附近5公里的人:
$filter = [
'location' => [
'$nearSphere' => [
'$geometry' => [
'type' => 'Point',
'coordinates' => [116.404, 39.915]
],
'$maxDistance' => 5000
]
]
];
$result = $collection->find($filter);
纯PHP计算实现
当不使用数据库空间函数时,可通过Haversine公式计算两点间距离:
function getDistance($lat1, $lng1, $lat2, $lng2) {
$earthRadius = 6371000; // 地球半径(米)
$latFrom = deg2rad($lat1);
$lngFrom = deg2rad($lng1);
$latTo = deg2rad($lat2);
$lngTo = deg2rad($lng2);
$latDelta = $latTo - $latFrom;
$lngDelta = $lngTo - $lngFrom;
$angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
cos($latFrom) * cos($latTo) * pow(sin($lngDelta / 2), 2)));
return $angle * $earthRadius;
}
// 示例:计算两点距离
$distance = getDistance(39.915, 116.404, 39.916, 116.405);
性能优化建议
对于大规模用户数据,建议采用以下优化策略:
- 使用Redis GEO实现高频访问场景
- 对MySQL/MongoDB的地理字段建立空间索引
- 采用分库分表策略按地域分布数据
- 使用缓存减少重复计算
- 考虑使用Elasticsearch的地理搜索功能
每种实现方式各有优劣,MySQL方案适合已有MySQL架构的场景,Redis适合高性能需求,MongoDB适合文档型数据结构,纯PHP计算适合小规模数据或特殊环境。


