【问题标题】:laravel sorting eloquent collection based on array matching valueslaravel 基于数组匹配值对 eloquent 集合进行排序
【发布时间】:2015-05-11 04:10:56
【问题描述】:

我正在尝试构建一个项目推荐系统,其中用户和项目具有所需的技能标签。我正在尝试根据每个技能数组中匹配的技能数量为用户生成和排序推荐项目的集合,例如,与用户技能最匹配的项目将首先出现在推荐列表中项目。

这是我目前的代码。

public function recommendedProjects()
{
    $projects = Project::all()->filter(function ($project) {

        foreach(unserialize($project->skills) as $projectSkill)
        {
            foreach(unserialize(Auth::user()->profile->skills) as $userSkill)
            {
                if($projectSkill === $userSkill)
                {
                    return true;
                }
            }
        }
    });

    return View::make('projects.projects')->with("title", "Recommended Projects")->with('projects', $projects);
}

到目前为止,它还算有效,但只返回具有至少一项匹配技能的项目。

如果我可以将结果数量限制在最相关的 20 个左右的项目中,那也会很有帮助。

感谢任何帮助,这是我的第一个 Laravel 项目,哈哈。

编辑

我更改了代码以将技能存储在他们自己的表中,而不是使用序列化,现在它返回具有至少一项匹配用户技能的所有项目。

我想对项目进行排序,以使技能与用户技能最匹配的项目首先出现。

例如,如果一个项目有 3 项必需技能,而用户拥有全部 3 项技能,则该项目将首先出现,然后是技能匹配较少的项目。

这是我更新的代码

  $projects = Project::all()->filter(function ($project) {

            foreach ($project->skills as $projectSkill) {
                foreach (Auth::user()->skills as $userSkill) {
                    if ($projectSkill->name === $userSkill->name) {
                        return true;
                    }
                }
            }

    });

【问题讨论】:

  • 几件事。这里的反序列化很糟糕。您应该查看 JSON 数组以获取技能,或者更推荐为技能创建关系。他们真的应该是他们自己的数据库模型。应在获取对象时进行反序列化,而不是按要求针对每个项目进行反序列化。您还为每个项目多次取消序列化用户技能。开销太大了。至于这个问题,我没有理由知道为什么它会返回一个项目而不是所有与用户技能相匹配的项目。
  • 感谢您的帮助!看看我的编辑!
  • 您还应该“急切地加载”具有防止n+1 问题的技能的项目。 See Here 。试试Project::with('skills')->get()

标签: php laravel


【解决方案1】:

您只需对您拥有的项目集合进行排序。试试这个:

$userSkills = Auth::user()->skills;

$projects = Projects::with('skills')->get();

$projects = $projects->sort(function($a, $b) use ($userSkills) {
    // Get the matching skills from both A and B
    $aMatchingSkills = $a->skills->intersect($userSkills);
    $bMatchingSkills = $b->skills->intersect($userSkills);

    // Return the count of A minus the count of B - See PHP uasort
    return $aMatchingSkills->count() - $bMatchingSkills->count();
});

这是非常广泛地使用 eloquent 集合对象(sortintersectcount)。 sort 使用 PHP 中一个非常有用的函数 - uasort

要删除没有匹配技能的项目,请尝试将Projects::with('skills')->get(); 位替换为...

Projects::with(['skills' => function($q) use ($userSkills) {
    $q->whereIn('name', $userSkills->fetch('name'));
}])->get();

现在这有点复杂,我不能保证我发布的内容会起作用,但它已经接近了。

【讨论】:

  • 感谢您的帮助,但它不起作用,它只是返回所有项目。
  • 他们现在排序了吗?我将编辑我的问题以过滤掉没有匹配技能的项目。
  • 聚会有点晚了,但您没有将$projects->sort 保存回变量,因此未使用排序结果。您需要像$projects = $projects->sort 一样重新分配它们。
  • 感谢您的更新。在撰写本文时,这种方法并不是一成不变的。不过我会在这里更新。
猜你喜欢
  • 1970-01-01
  • 2017-09-15
  • 2021-01-15
  • 1970-01-01
  • 2021-01-13
  • 1970-01-01
  • 2019-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多