whereIn(...)"; 2. Filter data through filter; 3. Set the sorted data to "$data = $scoutModelsLists;"."/> whereIn(...)"; 2. Filter data through filter; 3. Set the sorted data to "$data = $scoutModelsLists;".">

Home  >  Article  >  PHP Framework  >  How to solve laravel sorting failure problem

How to solve laravel sorting failure problem

藏色散人
藏色散人Original
2022-01-06 15:09:212196browse

Solution to laravel sorting failure: 1. Query data through "$query->whereIn(...)"; 2. Filter data through filter; 3. Set the sorted data to "$data = $scoutModelsLists;".

How to solve laravel sorting failure problem

The operating environment of this article: Windows 7 system, Laravel version 5.8, Dell G3 computer.

How to solve laravel sorting failure problem?

Laravel 5.8 scout7.0 Sorting failure solution using orderBy

Recently, when searching using elasticSearch6.2.4, I found that the sorting field is invalid, so here Record

Let’s take a look at the solution first. Without further ado, let’s go directly to the code

$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;

Problem analysis

The original query statement used is

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

Although the above query statement sets the sorting field, it is not sorted when it is finally output. After analysis, it is indeed sorted in the ES search results, but when it is finally output, the ES data structure is converted into a set. , no sorting field is added

Code analysis

File 1: /vendor/laravel/scout/src/builder.php About 261 lines - 305 lines

If you look closely at this file, there will be two methods: paginate and paginateRaw. The former returns the laravel collection, and the latter returns the native query structure of es.

The difference between the two codes lies in this block

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

File 2: vendor/tamayo/laravel-scout-elastic/src/ElasticsearchEngine.php Line 211, map method, because here we are using the ES engine, if you use other, it may be different, the code:

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);
    });
}

From the code point of view, if es searches for data, it will be converted and filtered to return a set that meets the conditions. If it is not satisfied, it will directly return empty

File 3: /vendor/laravel/scout/ src/Searchable.php is about 171 lines getScoutModelsByIds method, code

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();
}

This file is the focus, mainly because the orderBy sorting field is not added when the final return is made, so although es is sorted in the final output, here again It has been reset. In order to prevent other places from being unable to update after changing the component, sorting is added when the data is finally returned. Please refer to the beginning of the article for the plan.

It’s over for the time being, and I’ll improve it when it’s empty.

The latest five Laravel video tutorials (recommended)

The above is the detailed content of How to solve laravel sorting failure problem. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn