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

如何在MongoDB与Laravel/Eloquent中获取EmbedsMany关系的反向关联

Laravel-MongoDB 5.x 嵌入式关系反向关联实现方案

你说得没错,Mongo官方接手维护Laravel-MongoDB 5.x版本后,确实移除了4.x中自动生成的嵌入式关系反向关联功能(即直接通过$book->user获取父模型)。官方调整的原因是嵌入式文档本质是父文档的一部分,MongoDB原生设计中并没有给嵌入式文档自动存储父引用的机制,4.x的自动关联是包的额外封装,5.x版本更贴近MongoDB原生逻辑。

下面提供几种可行的替代实现方式:

1. 手动存储父模型引用(推荐)

在嵌入式模型中添加字段存储父模型的ID和类型,保存时手动赋值,再通过关联方法获取父模型,这是性能最稳定的方案。

代码示例:

// Book模型
class Book extends Model
{
    protected $fillable = ['title', 'user_id', 'user_type'];

    // 定义反向关联
    public function user()
    {
        return $this->belongsTo($this->user_type, 'user_id');
    }
}

保存嵌入式文档时手动设置父引用:

$user = User::first();
$book = new Book(['title' => 'MongoDB实战']);
// 存储父模型ID和类名
$book->user_id = $user->_id;
$book->user_type = User::class;
$user->books()->save($book);

之后就可以像4.x版本一样调用:

$book = Book::first();
$user = $book->user;

2. 通过查询父模型集合获取(无额外字段)

如果不想新增字段,可以直接查询父模型集合,找到包含当前嵌入式文档的记录。注意:数据量大时需要给books._id添加索引来提升性能。

代码示例:

// Book模型中自定义访问器
class Book extends Model
{
    public function getUserAttribute()
    {
        return User::where('books._id', $this->_id)->first();
    }
}

调用方式不变:

$book = Book::first();
$user = $book->user;

3. 使用MongoDB聚合查询(复杂场景)

对于需要筛选、投影的复杂场景,可以用MongoDB聚合管道实现:

// Book模型中自定义访问器
class Book extends Model
{
    public function getUserAttribute()
    {
        $pipeline = [
            ['$unwind' => '$books'],
            ['$match' => ['books._id' => $this->_id]],
            ['$project' => ['_id' => 1, 'name' => 1]] // 只返回需要的字段
        ];

        return User::raw()->aggregate($pipeline)->current();
    }
}

内容的提问来源于stack exchange,提问作者cfkane

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 08:50:58