首頁  >  文章  >  php框架  >  如何解決laravel排序失效問題

如何解決laravel排序失效問題

藏色散人
藏色散人原創
2022-01-06 15:09:212128瀏覽

laravel排序失效的解決方法:1、透過「$query->whereIn(...)」查詢資料;2、透過filter過濾資料;3、設定排序好的資料為「$data = $scoutModelsLists;」。

如何解決laravel排序失效問題

本文操作環境:Windows7系統、Laravel5.8版、Dell G3電腦。

如何解決laravel排序失效問題?

Laravel 5.8 scout7.0 使用orderBy 排序失效解決方案

最近在使用elasticSearch6.2.4 做搜尋時發現,排序欄位失效,所以在這記錄下

先看下解決方案,話不多說,直接上程式碼

$list = Article::search($words)->orderBy('created_at','desc')->paginateRaw(10)->toArray();
$results = $list['data'];
if ($results['hits']['total'] === 0) {
    return $this->model->newCollection();
}
$builder =new Builder(new static(),$this->model->newModelQuery());
$keys = collect($results['hits']['hits'])->pluck('_id')->values()->all();
$query = $this->newQuery();
if ($builder->queryCallback) {
    call_user_func($builder->queryCallback, $query);
}
//查询数据
$scoutModelsLists = $query->whereIn(
    $this->model->qualifyColumn($this->model->getKeyName()), $keys
)->orderBy('created_at','desc')->get();
//过滤数据
$scoutModelsLists->filter(function () use ($keys) {
    return in_array($this->model->getKey(), $keys);
});
//这里为最终排序好的数据
$data = $scoutModelsLists;

問題分析

原來使用的查詢語句為

$list = Article::search($words)->orderBy('created_at','desc')->paginate(10)->toArray();

上面查詢語句雖然設定了排序字段,但是最終輸出的時候卻沒有排序,經分析,在ES 搜尋結果裡面的確是排了序,但最終輸出時,ES 資料結構轉換為集合時,未加上排序欄位

程式碼分析

檔1: /vendor/laravel/scout/src/builder.php 約261 行- 305 行

仔細觀察這個檔案會有兩個方法paginate、paginateRaw ,前一個返回laravel 集合,後一個返回es 的原生查詢結構,

這兩者程式碼的不同點在於這塊

$results = $this->model->newCollection($engine->map(
        $this, $rawResults = $engine->paginate($this, $perPage, $page), $this->model
    )->all());

檔案2:vendor/tamayo/laravel-scout-elastic/src/ElasticsearchEngine.php 211 行,map 方法,因為這裡我們使用的是ES 引擎,如果使用別的,可能有所不同,程式碼:

public function map(Builder $builder, $results, $model)
{
//无数据返回空集合
if ($results['hits']['total'] === 0) {
    return $model->newCollection();
}
//获取所有键为_id的ES数据
//$keys = collect($results['hits']['hits'])->pluck('_id')->values()->all();
//转化ES数据并过滤
return $model->getScoutModelsByIds(
        $builder, $keys
    )->filter(function ($model) use ($keys) {
        return in_array($model->getScoutKey(), $keys);
    });
}

從程式碼看來,es 搜尋出來有數據,則轉換並過濾一下返回符合條件的集合,不滿足直接返回空

檔案3: /vendor/laravel/scout/ src/Searchable.php 約171 行getScoutModelsByIds 方法,程式碼

public function getScoutModelsByIds(Builder $builder, array $ids)
{
//加入软删除
$query = static::usesSoftDelete()
    ? $this->withTrashed() : $this->newQuery();
if ($builder->queryCallback) {
    call_user_func($builder->queryCallback, $query);
}
// 重点这里,自改代码
// return $query->whereIn(
  //   $this->getScoutKeyName(), $ids
// )->orderBy('orderBy','desc')->get();
//官方代码
return $query->whereIn(
    $this->getScoutKeyName(), $ids
)->get();
}

這個檔案是重點,主要是這裡最後回傳的時候並沒有加上orderBy 排序字段,所以最後輸出時雖然es 排序了,這裡又重置了,為防止改組件後其他地方無法更新,所以在最後回傳資料時加了排序處理,方案參考文章開頭。

暫時告一段落,空了再完善。

最新的五個Laravel影片教學(推薦)

#

以上是如何解決laravel排序失效問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn