Laravel 5 Eloquent查询效率中带有过滤器的多个内连接

时间:2015-10-25 09:14:54

标签: eloquent laravel-5.1

我有以下模型和关系: 广告与城市有多对多的关系 广告具有多对多的类别

现在我想获得特定城市和特定类别的广告。所以在SQL中我执行以下操作并获得正确的结果:

select * from ads
inner join ad_cities on ad_cities.adId = ads.id
inner join ad_categories on ad_categories.adId = ads.id
where ad_cities.cityId = 1525
and ad_categories.categoryId = 6

我知道可以使用DB:table(xxxx) - > join-> .... 但我想知道在不采用DB:table方法的情况下是否可以在模型上完成相同的操作。

我尝试了以下内容并获得了结果,但生成的查询似乎并不高效。

return Category::find(6)
            ->ads()
            ->whereHas('cities', function ($query) {
                    $query->where('cityId', '=', '1525');
                    })                    
            ->where('statusName', '=', 'PUBLISHED')
            ->orderBy('publishedAt', 'DESC')
            ->simplePaginate($pageSize);

这会生成以下查询:

select `ads`.*, `ad_categories`.`categoryId` as `pivot_categoryId`, `ad_categories`.`adId` as `pivot_adId` from `ads` inner join `ad_categories` on `ads`.`id` = `ad_categories`.`adId` where `ad_categories`.`categoryId` = '6' and (select count(*) from `cities` inner join `ad_cities` on `cities`.`id` = `ad_cities`.`cityId` where `ad_cities`.`adId` = `ads`.`id` and `cityId` = '1525') >= 1 and `statusName` = 'PUBLISHED' order by `publishedAt` desc limit 16 offset 0

感谢您的帮助。 谢谢, Velu

1 个答案:

答案 0 :(得分:0)

我已经花了很长时间在我自己的项目中对抗这个问题,我能做的最好的就是:

return Category::find(6)
            ->ads()
            ->join('ad_cities', 'ad_cities.adId', '=', 'ads.id')
            ->where('ad_cities.cityId', 1525)                   
            ->where('statusName', '=', 'PUBLISHED')
            ->orderBy('publishedAt', 'DESC')
            ->simplePaginate($pageSize);

这是对的,对吧?它为您提供了正确的SQL并在某种程度上保留了Eloquent API。我正在做的另一件事,我甚至无法解决这个问题,在使用原始SQL获取后使用hydratehydrateRaw

这样,当有一天我弄清楚如何有效地使用Eloquent和/或Eloquent成熟时,模型和控制器之间的接口仍然是正确的,我可以用ORM的优点替换SQL。

另外,如果您找到更好的方法,请告诉我。