You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:48:06