如何使用Elasticsearch实现查询“附近的人”?

提问者:帅平 问题分类:微服务
“附近的人”现在几乎是很多ToC应用的标配,请问如何使用Elasticsearch实现查询“附近的人”?
3 个回答
孤岛少女情
孤岛少女情
把用户的经纬度存进去,然后使用java进行查询即可,示例如下:
// 查找附近用户的方法
    public SearchResponse findNearbyUsers(Double targetLat, Double targetLon, Double distanceInKm) throws IOException {
        // 创建搜索请求,并设置GeoDistance查询
        SearchRequest searchRequest = new SearchRequest("users");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        GeoDistanceQueryBuilder geoDistanceQueryBuilder = QueryBuilders.geoDistanceQuery("location")
                .point(targetLat, targetLon)
                .distance(distanceInKm, DistanceUnit.KILOMETERS);
        searchSourceBuilder.query(geoDistanceQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        return client.search(searchRequest, RequestOptions.DEFAULT);
    }
发布于:1个月前 (03-21) IP属地:四川省
最后一丝温柔
最后一丝温柔
再给个mysql的使用示例:
// 查找附近用户的方法(使用Haversine公式)
    public List<User> findNearbyUsers(Double targetLat, Double targetLon, Double distanceInKm) {
        // Haversine公式计算距离并构造SQL查询
        // 注意:这里的实现是简化的,为了性能优化,通常不会直接在Java代码中拼接SQL
        // 而在实际应用中,应该使用参数化查询来防止SQL注入
        String sql = "SELECT * FROM users WHERE (" +
                "6371 * 2 * ASIN(SQRT(POWER(SIN((" + targetLat + " - latitude) * PI() / 180 / 2), 2) +" +
                "POWER(COS(" + targetLat + " * PI() / 180) * SIN((" + targetLon + " - longitude) * PI() / 180 / 2), 2))) <= " + distanceInKm;
        return userMapper.selectBySql(sql);
    }
发布于:1个月前 (03-21) IP属地:四川省
帅的被人砍
帅的被人砍
再给一个redis实现“附近的人”的案例:
// 更新用户位置信息
    public void updateUserLocation(Long userId, Double longitude, Double latitude) {
        redisTemplate.opsForGeo().add("user_location", new Point(longitude, latitude), userId);
    }
// 获取附近用户
    public List<Long> getNearbyUsers(Double longitude, Double latitude, Double radius) {
        Distance distance = new Distance(radius, Metrics.KILOMETERS);
        Circle circle = new Circle(new Point(longitude, latitude), distance);
        GeoResults<GeoLocation<Object>> geoResults = redisTemplate.opsForGeo().radius(USER_LOCATION_KEY, circle);
        List<Long> nearbyUsers = new ArrayList<>();
        for (GeoResult<GeoLocation<Object>> geoResult : geoResults.getContent()) {
            Object memberId = geoResult.getContent().getName();
            nearbyUsers.add((Long) memberId);
        }
        return nearbyUsers;
    }
}
发布于:1个月前 (03-21) IP属地:四川省
我来回答