我有一个 SQL 查询,如下所示:
SELECT * FROM orders FORCE INDEX(order_type_index) WHERE `type` = 1
我可以使用查询生成器来重新创建它:
DB::table(DB::raw('orders force index(orders_type_index)'))
->where('type', 1)
->get();
但是有没有办法让 Eloquent 使用这个索引,比如:
Order::forceIndex('orders_type_index')->where('type', 1)->get();
您可以通过创建一个来做到这一点局部范围 https://laravel.com/docs/8.x/eloquent#local-scopes应用时会更改构建器的表名称。在使用表之前应检查该表的索引。如果提供了无效的索引名称,您可以抛出异常或忽略它(我选择了后一种方法。)
<?php
namespace App;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
/*
* Class Order
*
* @method \Illuminate\Database\Eloquent\Builder useIndex(string $index)
* @method \Illuminate\Database\Eloquent\Builder forceIndex(string $index)
*/
class Order extends Model
{
private function tableIndexExists(string $index): boolean
{
$table = $this->getTable();
$index = strtolower($index);
$indices = Schema::getConnection()
->getDoctrineSchemaManager()
->listTableIndexes($table);
return array_key_exists($index, $indices);
}
public function scopeUseIndex(Builder $query, string $index): Builder
{
$table = $this->getTable();
return $this->tableIndexExists($index)
? $query->from(DB::raw("`$table` USE INDEX(`$index`)"))
: $query;
}
public function scopeForceIndex(Builder $query, string $index): Builder
{
$table = $this->getTable();
return $this->tableIndexExists($index)
? $query->from(DB::raw("`$table` FORCE INDEX(`$index`)"))
: $query;
}
}
如果您需要在多个模型上执行此操作,可以轻松地将其添加到特征中并导入。文档块确保您的 IDE 知道代码完成的神奇方法。
然后你可以像这样使用它:
$orders = Order::forceIndex("orders_type_index")->where("type", 1)->get();
// or this:
$orders = Customer::find(234)
->orders()
->forceIndex("orders_type_index")
->where("type", 1)
->get();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)