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

原来

$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);

    }
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 14

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

1年前 评论

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

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

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

1年前 评论

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

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

1年前 评论

为什么又用 join 又用 with

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

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

这不慢就有鬼了:joy:

1年前 评论

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

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

1年前 评论

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

1年前 评论

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