Laravel中查询双向点赞匹配记录的实现方法
嘿,我完全懂你要解决的双向匹配问题——就是要找出那些互相点赞的用户对吧?这种场景在交友类应用里太常见了,我来给你几种Laravel里的实现方式,肯定能帮到你!
首先先假设你的点赞表结构大概是这样的(如果和你的实际结构有出入,调整字段名就行):
// 迁移文件示例 Schema::create('likes', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('from_profile_id'); // 发起点赞的profile ID $table->unsignedBigInteger('to_profile_id'); // 被点赞的profile ID $table->timestamps(); // 建议添加唯一约束,防止同一个用户重复点赞同一对象 $table->unique(['from_profile_id', 'to_profile_id']); });
方法一:使用自连接(Self Join)构建查询
这种方式通过将likes表与自身关联,直接匹配出双向点赞的记录:
$mutualMatches = DB::table('likes as l1') ->join('likes as l2', function ($join) { // 关联条件:l1的点赞发起者是l2的被点赞者,且l1的被点赞者是l2的发起者 $join->on('l1.from_profile_id', '=', 'l2.to_profile_id') ->on('l1.to_profile_id', '=', 'l2.from_profile_id'); }) // 加上这个条件避免重复返回同一组匹配(比如(1,2)和(2,1)会被视为同一组) ->where('l1.from_profile_id', '<', 'l1.to_profile_id') ->select( 'l1.from_profile_id as profile_a', 'l1.to_profile_id as profile_b' ) ->distinct() ->get();
方法二:使用whereExists子查询
如果你更倾向于子查询的写法,这种方式也能实现相同效果:
$mutualMatches = DB::table('likes') ->select('from_profile_id as profile_a', 'to_profile_id as profile_b') ->whereExists(function ($query) { // 子查询检查:当前这条点赞记录(A→B)是否存在对应的反向点赞(B→A) $query->select(DB::raw(1)) ->from('likes as l2') ->whereColumn('l2.from_profile_id', 'likes.to_profile_id') ->whereColumn('l2.to_profile_id', 'likes.from_profile_id'); }) // 同样避免重复结果 ->where('from_profile_id', '<', 'to_profile_id') ->distinct() ->get();
如果你用Eloquent模型
假设你已经创建了Like模型,也可以用Eloquent的查询语法来写:
use App\Models\Like; $mutualMatches = Like::query() ->select('from_profile_id as profile_a', 'to_profile_id as profile_b') ->whereExists(function ($query) { $query->select(DB::raw(1)) ->from('likes as l2') ->whereColumn('l2.from_profile_id', 'likes.to_profile_id') ->whereColumn('l2.to_profile_id', 'likes.from_profile_id'); }) ->where('from_profile_id', '<', 'to_profile_id') ->distinct() ->get();
额外场景:查询某个特定Profile的匹配对象
如果要找出某个特定用户(比如ID为1的profile)的所有双向匹配对象,可以这么写:
$targetProfileId = 1; $matches = DB::table('likes as l1') ->join('likes as l2', function ($join) use ($targetProfileId) { $join->on('l1.to_profile_id', '=', $targetProfileId) ->on('l2.from_profile_id', '=', $targetProfileId) ->on('l1.from_profile_id', '=', $l2.to_profile_id); }) ->select('l1.from_profile_id as matched_profile_id') ->distinct() ->get();
最后提个小建议:如果你的likes表已经给from_profile_id和to_profile_id组合添加了唯一约束,或者给这两个字段单独加了索引,查询效率会提升不少哦!
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

