与具有模糊列名称的范围进行雄辩联接

时间:2017-06-19 22:02:16

标签: mysql laravel eloquent left-join

我有两张表venuesvenue_plans,有hasOne关系。前者包含地理位置数据,而后者包含距离奖励",因此距离奖励越多,场地将显示给在其位置周围搜索的用户越近。

还有第三个表categories,它与hasMany关系。基本上,每个场地都可以设置多个类别,就像那样简单。

我已设法添加到范围:第一个计算距离给定位置的距离(例如,用户位置),计算距离奖励并按两个字段对场地进行排序:

public function scopeWithDistanceFrom($query, $lat, $lng, $units = 'km') {
    $units = ($units === "km") ? 6378.10 : 3963.17;
    $lat = (float) $lat;
    $lng = (float) $lng;
    $lat_column = 'geo_latitude';
    $lng_column = 'geo_longitude';

    // Join with venue_plans to get the distance bonus
    $query->leftJoin('venue_plans', 'venues.id', 'venue_plans.venue_id');

    // Add distance column
    $distance_raw = "$units * ACOS(
                        COS(RADIANS($lat)) * COS(RADIANS($lat_column))
                        * COS(RADIANS($lng) - RADIANS($lng_column))
                        + SIN(RADIANS($lat)) * SIN(RADIANS($lat_column))
                    ) AS distance";
    $query->selectRaw($distance_raw);

    // Add distance_bonused column
    $distance_bonused_raw = "(SELECT (distance - (distance / 100 * distance_bonus))) as distance_bonused";
    $query->selectRaw($distance_bonused_raw);

    // Sort by distance
    $query->orderBy('distance_bonused', 'desc');
    $query->orderBy('distance', 'desc');

    return $query;
}

第二个按名称(venue.name)或类别名称(categories.name)搜索场地。

public function scopeWithNameOrCategoryName($query, $name) {
    return $query
        ->where('name', 'like', "%{$name}%") // Venue name
        ->orWhereHas('categories', function($query) use ($name){ // Category name
            $query->where('name', 'like', "%{$name}%");
        });
}

虽然它们在单独使用时都可以正常工作,但是当我一起使用它们时,就像

一样
Venue::withNameOrCategory('myname')
    ->withDistanceFrom(35.0386, 13.92)
    ->take(5)->get();

我收到此错误:

SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'name' in where clause is ambiguous (SQL: select `venues`.*, 6378.1 * ACOS(COS(RADIANS(35.0386)) * COS(RADIANS(geo_latitude)) * COS(RADIANS(13.92) - RADIANS(geo_longitude)) + SIN(RADIANS(35.0386)) * SIN(RADIANS(geo_latitude))) AS distance, (SELECT (distance - (distance / 100 * distance_bonus))) as distance_bonused from `venues` left join `venue_plans` on `venues`.`id` = `venue_plans`.`venue_id` where (`name` like %myname% or exists (select * from `categories` inner join `category_venue` on `categories`.`id` = `category_venue`.`category_id` where `venues`.`id` = `category_venue`.`venue_id` and `categories`.`name` like %myname%)) order by `distance_bonused` desc, `distance` desc limit 5)

我应该提一下,即使venue_plans表格都有一个name列,也可以存储选定的计划名称,并使其保持特定的位置。

有人可以向我解释一下,最干净的方法是什么?如果可能的话,我也会避免使用表名和连接。

由于

0 个答案:

没有答案