Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Laravel 获取包含10个项目的缓存雄辩集合超时_Laravel_Redis - Fatal编程技术网

Laravel 获取包含10个项目的缓存雄辩集合超时

Laravel 获取包含10个项目的缓存雄辩集合超时,laravel,redis,Laravel,Redis,我正在构建一个搜索功能,返回使用LengthAwarePaginator分页的大型集合。我正在尝试使用一个名为$searchFilter\u$query\u$offsetPages的键缓存返回结果的一页(10项)。它很好地进入了缓存。但是,当我尝试使用Cache::has($key)检查或使用Cache::get($key)获取时,它会超时 浏览器和artisan Tinker中也会出现同样的问题。奇怪的是,当我在Tinker中将一组随机的10个项目放入缓存并取回时,一切都正常。我使用Redis

我正在构建一个搜索功能,返回使用LengthAwarePaginator分页的大型集合。我正在尝试使用一个名为$searchFilter\u$query\u$offsetPages的键缓存返回结果的一页(10项)。它很好地进入了缓存。但是,当我尝试使用Cache::has($key)检查或使用Cache::get($key)获取时,它会超时

浏览器和artisan Tinker中也会出现同样的问题。奇怪的是,当我在Tinker中将一组随机的10个项目放入缓存并取回时,一切都正常。我使用Redis作为缓存驱动程序

以下是我的控制器方法:

public function search($filter, $query, $layout, Request $request) {
  if($layout == "list-map") {
    return view("list-map")->with(['filter' => $filter, 'query' => $query, 'layout' => 'list-map']);      
  } else {
    $offsetPages = $request->input('page', 1) - 1;
    $cacheKey = $filter . "_" . $query . "_" . $offsetPages;

    if(Cache::has($cacheKey)) {
      \Log::info("fetching results from cache");
      $data = Cache::get($cacheKey);

      $totalCt = $data[0];
      $results = $data[1];
    } else {
      $results = $this->getResults($filter, $query);
      $totalCt = $results->count();
      $results = $results->slice($offsetPages, $this->resultsPerPage);

      \Log::info("caching results");
      Cache::put($cacheKey, [$totalCt, $results], 5);
    }

  $results = new LengthAwarePaginator($results,
    $totalCt,
    $this->resultsPerPage,
    $request->input('page', 1),
    ['path' => LengthAwarePaginator::resolveCurrentPath()]
  );

    return view($layout)->with(['filter' => $filter, 'query' => $query, 'layout' => $layout, 'results' => $results]);
  }

}

我真的不明白为什么你的代码不起作用。我看到的唯一潜在问题是缓存键,它可能包含有问题的字符,以及检查缓存值的方式。当您在
Cache::has($key)
之前使用
Cache::get($key)
时,您可能会遇到一个竞争条件,其中第一个调用返回
true
,而后一个调用返回
null
,因为缓存值刚好在两个调用之间超时

我试图在以下片段中解决这两个问题:

public function search($filter, $query, $layout, Request $request)
{
    if($layout == "list-map") {
        return view("list-map")->with(['filter' => $filter, 'query' => $query, 'layout' => 'list-map']);      
    } else {
        $offsetPages = $request->input('page', 1) - 1;
        $cacheKey = md5("{$filter}_{$query}_{$offsetPages}");
        $duration = 5; // todo: make this configurable or a constant

        [$totalCount, $results] = Cache::remember($cacheKey, $duration, function () use ($filter, $query) {
            $results = $this->getResults($filter, $query);
            $totalCount = $results->count();
            $filteredResults = $results->slice($offsetPages, $this->resultsPerPage);

            return [$totalCount, $filteredResults];
        });

        $results = new LengthAwarePaginator($results,
            $totalCount,
            $this->resultsPerPage,
            $request->input('page', 1),
            ['path' => LengthAwarePaginator::resolveCurrentPath()]
        );

        return view($layout)->with(compact('filter', 'query', 'layout', 'results'));
    }
}
内置函数
Cache::memory()
没有在引擎盖下使用
Cache::has()
。相反,它只需调用
Cache::get()
。由于如果未命中缓存,此函数将返回默认值
null
,因此该函数可以轻松确定是否必须执行关闭

我还在
md5()
中包装了
$cacheKey
,它提供了一个一致有效的密钥


查看代码的以下部分

$results = $this->getResults($filter, $query);
$totalCount = $results->count();
$filteredResults = $results->slice($offsetPages, $this->resultsPerPage);

我确信整个搜索可以得到改进(独立于缓存)。因为看起来您正在将特定搜索的所有结果加载到内存中,即使您丢弃了其中的大部分内容。当然有更好的方法可以做到这一点。

因此,问题是从我的getResults()方法返回的集合中的许多模型都是通过关系查询获得的。当我在10个结果的单一页面上添加($results)时,我可以看到每个模型上都有一个“relations”字段。在这个数组中,有数千个基于我最初查询的关系的递归相关模型。我找不到任何关于不急于加载这些相关模型的选项的信息。取而代之的是,我想出了一个简单的方法来直接获取模型:

  $results = $results->slice($offsetPages, $this->resultsPerPage);

      //load models directly so they don't include related models.
      $temp = new \Illuminate\Database\Eloquent\Collection;
      foreach($results as $result) {
        if(get_class($result) == "App\Doctor") {
          $result = Doctor::find($result->id);
        } else if(get_class($result == "App\Organization")) {
          $result = Organization::find($result->id);
        }
        $temp->push($result);
      }
      $results = $temp;

      \Log::info("caching results");
      Cache::put($cacheKey, [$totalCt, $results], 5);
如果有人知道这种情况下的最佳做法,请告诉我。谢谢

编辑:
我找到了一个更好的解决方案,而不是上述解决方法。如果我像这样查询我的关系:$taxonomy->doctors()->get(),而不是$taxonomy->doctors,它不会加载在巨大的重复关系中。

什么内容有
$filter
?可能会对其构建一个散列,以防止在缓存键中使用不允许的字符。$filter可以是“医生”、“诊所”或“全部”,而
$query
?另外,$query不包含空格。它们在路线关闭中被下划线替换,然后重定向到此控制器方法。dd($cacheKey)=>医生\u药物滥用\u 0感谢您的反馈。我来看看散列键是否有什么不同。起初我确实尝试过使用memory函数,但我想我在调用$this->getResults()时遇到了一个问题,因为我认为$this在闭包中超出了范围。之前我尝试将其设置为$self并使用use传入,但我认为这仍然存在问题。我只是尝试将条件更改为if(!is_null($data=Cache::get($cacheKey)),而不是使用has后跟get。问题仍然存在。散列键也没有什么不同。啊,这与我返回的集合有关。当我简单地获取前500条记录、切片和缓存时,它工作得很好。我将继续调查从$this->getResults()返回的内容。我会告诉你我发现了什么。谢谢。问题是我通过关系获取了集合中的大多数模型,并且它加载到与每个模型相关的所有内容中。因此,当我dd()并检查一个模型时,有一个“relations”数组保存所有相关的模型。有没有不包含这些相关模型的方法?这是一个罕见的用例,但可能
$model->newquerywhithoutrelationships()
适合此任务(在查询结果时,根本不加载关系)。您还可以在加载关系后,使用
$model->unsetrelationship('doctor')
卸载关系(这没有多大意义)。我认为如果你优化了你的查询,你根本不需要缓存……我不确定我该如何优化它,因为它需要查询多个表,有时需要通过关系查询两个层次,以获取有意义的搜索结果。谢谢你的建议!如果不需要一个关系的多个子行,您还可以手动构建带有连接的查询。也许这是另一个问题这可能很理想,但我对目前的状况很满意。我需要推进这个项目。谢谢你的洞察力。