不懂就问,这么写,是不是很费资源。。。

原来

$merchants = Merchant::where('ident_status',10)
                        ->select('id', 'company_name', 'store_pic', 'goods_category', 'location_name', 'latitude', 'longitude')
                        ->selectRaw(\DB::raw('(6371 * acos(cos(radians(' . $userLatitude . ')) * cos(radians(latitude)) * cos(radians(longitude) - radians(' . $userLongitude . ')) + sin(radians(' . $userLatitude . ')) * sin(radians(latitude)))) AS distance'))
                        ->with('merchant_goods:id,merchant_id,merchant_goods_total_price,merchant_goods_sell_price,merchant_goods_title')
                        ->orderBy('created_at', 'desc')
                        ->paginate(10);

其中,下面是在算用户和商户的实时距离

selectRaw(\DB::raw('(6371 * acos(cos(radians(' . $userLatitude . ')) * cos(radians(latitude)) * cos(radians(longitude) - radians(' . $userLongitude . ')) + sin(radians(' . $userLatitude . ')) * sin(radians(latitude)))) AS distance'))

现在更复杂了

merchant 和 merchant_goods 两张表,要在merchant计算距离,要在merchant_goods统计商户的所有商品销量,还要列出merchant对应的所有merchant_goods,

$merchantsQuery = Merchant::join('merchant_goods', 'merchants.id', '=', 'merchant_goods.merchant_id')
                    ->where('merchants.ident_status', 10)
                    ->has('merchant_goods')
                    ->select('merchants.id', 'merchants.user_id', 'merchants.company_name', 'merchants.store_pic', 'merchants.goods_category', 'merchants.location_name', 'merchants.latitude', 'merchants.longitude')
                    ->selectRaw(\DB::raw('(6371 * acos(cos(radians(' . $userLatitude . ')) * cos(radians(merchants.latitude)) * cos(radians(merchants.longitude) - radians(' . $userLongitude . ')) + sin(radians(' . $userLatitude . ')) * sin(radians(merchants.latitude)))) AS distance'))
                    ->selectRaw('SUM(merchant_goods.fake_sell_count) AS fake_sell_count')
                    ->groupBy('merchants.id', 'merchants.user_id', 'merchants.company_name', 'merchants.store_pic', 'merchants.goods_category', 'merchants.location_name', 'merchants.latitude', 'merchants.longitude')
                    ->with('merchant_goods:id,merchant_id,merchant_goods_total_price,merchant_goods_sell_price,merchant_goods_title');

        if($category == 'default') {
            $merchantsQuery->orderBy('merchants.created_at', 'desc');
        }

        if($category == 'lbs') {
            $merchantsQuery->orderBy('distance', 'asc');
        }

        if($category == 'sell') {
            $merchantsQuery->orderBy('fake_sell_count', 'desc');
        }

        $merchants = $merchantsQuery->paginate(7);

model优化版(计算在model里了,但是速度更慢了,同时100条1.2s,直接写sql里算900ms左右)

public function list(Request $request) {

        $category = $request->category;

        $userLatitude = $request->latitude;

        $userLongitude = $request->longitude;

        //select、with的时候id或者ORM匹配的字段一定要有,不然with会失效
        $merchantsQuery = Merchant::join('merchant_goods', 'merchants.id', '=', 'merchant_goods.merchant_id')
                    ->where('merchants.ident_status', 10)
                    ->has('merchant_goods')
                    ->select('merchants.id', 'merchants.user_id', 'merchants.company_name', 'merchants.store_pic', 'merchants.goods_category', 'merchants.location_name', 'merchants.latitude', 'merchants.longitude')
                    ->selectRaw('SUM(merchant_goods.fake_sell_count) AS fake_sell_count')
                    ->groupBy('merchants.id', 'merchants.user_id', 'merchants.company_name', 'merchants.store_pic', 'merchants.goods_category', 'merchants.location_name', 'merchants.latitude', 'merchants.longitude')
                    ->with('merchant_goods:id,merchant_id,merchant_goods_total_price,merchant_goods_sell_price,merchant_goods_title');

        // 在这里输出$merchants之前,可以对其进行遍历,计算每个商家距离用户的距离
        foreach ($merchantsQuery->get() as $merchants) {
            $merchants->distance; // 访问距离属性,会触发getDistanceAttribute()方法进行计算
        }

        if($category == 'default') {
            $merchantsQuery->orderBy('merchants.created_at', 'desc');
        }

        if($category == 'lbs') {
            $merchantsQuery->orderBy('merchants.distance', 'asc');
        }

        if($category == 'sell') {
            $merchantsQuery->orderBy('fake_sell_count', 'desc');
        }

        $merchants = $merchantsQuery->paginate(100);

        return response()->json(['data' => $merchants],201);

    }
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 14

计算的可以拿出来在代码中计算

3年前 评论

计算部分强烈建议不要在 mysql 中进行

3年前 评论
wongvio (楼主) 3年前
23tl (作者) 3年前
wongvio (楼主) 3年前
it_cwc 3年前
wongvio (楼主) 3年前
pi_phq 3年前
王小大 3年前
gongmeng

如非不得已,不要使用mysql函数处理sql

3年前 评论

是,但是在高版本的 MySQL 中,也添加 GIS 方面的支持,提供了空间索引,比你这样的效率要高。

如果你的 MySQL 还不支持,那如果数据量不大,可以放到代码里面去算,如果数据量稍多,可以放到 Redis 里面,如果数据量巨大,可以放到 ElasticSearch 里面。

3年前 评论

为什么又用 join 又用 with ?

而且这里用 get ,你就已经查询了一次数据了(而且是没有做分页,对所有符合条件的数据都做了一次计算),后面再 paginate 是第二次查询。

 foreach ($merchantsQuery->get() as $merchants) 

这不慢就有鬼了:joy:。

3年前 评论

mysql有现成的计算距离的函数,根本不需要三角函数,

select ST_Distance_Sphere( point(-87.6770458, 41.9631174), point(-73.9898293, 40.7628267) )

3年前 评论

合理运用数据库视图可以很好的解耦代码上的复杂度。

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!