如何解決laravel排序失效問(wèn)題

laravel排序失效的解決辦法:1、通過(guò)“$query->whereIn(…)”查詢數(shù)據(jù);2、通過(guò)filter過(guò)濾數(shù)據(jù);3、設(shè)置排序好的數(shù)據(jù)為“$data = $scoutModelsLists;”。

如何解決laravel排序失效問(wèn)題

本文操作環(huán)境:Windows7系統(tǒng)、Laravel5.8版、Dell G3電腦。

如何解決laravel排序失效問(wèn)題?

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

最近在使用 elasticSearch6.2.4 做搜索時(shí)發(fā)現(xiàn),排序字段失效,所以在這記錄下

先看下解決方案,話不多說(shuō),直接上代碼

$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); } //查詢數(shù)據(jù) $scoutModelsLists?=?$query->whereIn( ????$this->model->qualifyColumn($this->model->getKeyName()),?$keys )->orderBy('created_at','desc')->get(); //過(guò)濾數(shù)據(jù) $scoutModelsLists->filter(function?()?use?($keys)?{ ????return?in_array($this->model->getKey(),?$keys); }); //這里為最終排序好的數(shù)據(jù) $data?=?$scoutModelsLists;

問(wèn)題分析

原來(lái)使用的查詢語(yǔ)句為

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

上面查詢語(yǔ)句雖然設(shè)置了排序字段,但是最終輸出的時(shí)候卻沒(méi)有排序,經(jīng)分析,在 ES 搜索結(jié)果里面的確是排了序,但最終輸出時(shí),ES 數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化為集合時(shí),并未加上排序字段

代碼分析

文件 1: /vendor/laravel/scout/src/builder.php 約 261 行 – 305 行

仔細(xì)觀察這個(gè)文件會(huì)有兩個(gè)方法 paginate、paginateRaw ,前一個(gè)返回 laravel 集合,后一個(gè)返回 es 的原生查詢結(jié)構(gòu),

這兩者代碼的不同點(diǎn)在于這塊

$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 方法,因?yàn)檫@里我們使用的是 ES 引擎,如果使用別的,可能有所不同,代碼:

public?function?map(Builder?$builder,?$results,?$model) { //無(wú)數(shù)據(jù)返回空集合 if?($results['hits']['total']?===?0)?{ ????return?$model->newCollection(); } //獲取所有鍵為_(kāi)id的ES數(shù)據(jù) //$keys?=?collect($results['hits']['hits'])->pluck('_id')->values()->all(); //轉(zhuǎn)化ES數(shù)據(jù)并過(guò)濾 return?$model->getScoutModelsByIds( ????????$builder,?$keys ????)->filter(function?($model)?use?($keys)?{ ????????return?in_array($model->getScoutKey(),?$keys); ????}); }

從代碼看來(lái),es 搜索出來(lái)有數(shù)據(jù),則轉(zhuǎn)化并過(guò)濾一下返回符合條件的集合,不滿足直接返回空

文件 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); } //?重點(diǎn)這里,自改代碼 //?return?$query->whereIn( ??//???$this->getScoutKeyName(),?$ids //?)->orderBy('orderBy','desc')->get(); //官方代碼 return?$query->whereIn( ????$this->getScoutKeyName(),?$ids )->get(); }

這個(gè)文件是重點(diǎn),主要是這里最后返回的時(shí)候并沒(méi)有加上 orderBy 排序字段,所以最后輸出時(shí)雖然 es 排序了,這里又重置了,為防止改組件后其他地方無(wú)法更新,所以在最后返回?cái)?shù)據(jù)時(shí)加了排序處理,方案參考文章開(kāi)頭。

暫時(shí)告一段落,空了再完善。

最新的五個(gè)Laravel視頻教程(推薦)

以上就是如何解決

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊7 分享