Laravel MongoDB 库 'jenssegers/laravel-mongodb' hasMany 关系无效

Laravel MongoDB library 'jenssegers/laravel-mongodb' hasMany relationship is not working

我在 Laravel 5.3.28 中使用 MongoDB 库 https://github.com/jenssegers/laravel-mongodb version 3.1.0-alpha 我在 MongoDB 中有两个 collection,我想制作一个 hasMany 关系 b/w 他们。意味着每个 Employee 执行许多任务。我在任务collection中使用了参考并添加了employee_ids。

下面是我的代码:

MongoDB:

第一个 Collection:员工

{
    "_id" : ObjectId("586ca8c71a72cb07a681566d"),
    "employee_name" : "John",
    "employee_description" : "test description",
    "employee_email" : "john@email.com",
    "updated_at" : "2017-01-04 11:45:20",
    "created_at" : "2017-01-04 11:45:20"
},
{
    "_id" : ObjectId("586ca8d31a72cb07a6815671"),
    "employee_name" : "Carlos",
    "employee_description" : "test description",
    "employee_email" : "carlos@email.com",
    "updated_at" : "2017-01-04 11:45:20",
    "created_at" : "2017-01-04 11:45:20"
}

第二个Collection:任务

{
    "_id" : ObjectId("586ccbcf1a72cb07a6815b04"),
    "task_name" : "New Task",
    "task_description" : "test description",
    "task_status" : 1,
    "task_start" : "2017-04-01 12:00:00",
    "task_end" : "2017-04-01 02:00:00",
    "task_created_at" : "2017-04-01 02:17:00",
    "task_updated_at" : "2017-04-01 02:17:00",
    "employee_id" : [ 
        ObjectId("586ca8c71a72cb07a681566d"), 
        ObjectId("586ca8d31a72cb07a6815671")
    ]
},
{
    "_id" : ObjectId("586cd3261a72cb07a6815c69"),
    "task_name" : "2nd Task",
    "task_description" : "test description",
    "task_status" : 1,
    "task_start" : "2017-04-01 12:00:00",
    "task_end" : "2017-04-01 02:00:00",
    "task_created_at" : "2017-04-01 02:17:00",
    "task_updated_at" : "2017-04-01 02:17:00",
    "employee_id" : ObjectId("586ca8c71a72cb07a681566d")
}

Laravel: 模型: 员工:

<?php
namespace App\Models;

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class Employee extends Eloquent {

    protected $collection = 'employee';
    protected $primaryKey = '_id';

    public function tasks()
    {
        return $this->hasMany('App\Models\Task');
    }
}

Laravel: 模型: 任务:

<?php
namespace App\Models;

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class Task extends Eloquent {

    protected $collection = 'task';
    protected $primaryKey = '_id';

    public function employees()
    {
        return $this->belongsTo('App\Models\Employee');
    }
} 

我想获得分配给特定员工的任务。

控制器:

public function EmployeeData($data)
{
    $employees = Employee::with('tasks')->where('_id', new \MongoDB\BSON\ObjectID('586ca8d31a72cb07a6815671'))->get();
        echo "<pre>";
        print_r($employees);exit;
}

输出:

Illuminate\Database\Eloquent\Collection Object
(
    [items:protected] => Array
        (
            [0] => App\Models\Employee Object
                (
                    [connection:protected] => mongodb
                    [collection:protected] => lt_employees
                    [primaryKey:protected] => _id
                    [employee_id:App\Models\Employee:private] => 
                    [employee_name:App\Models\Employee:private] => 
                    [employee_description:App\Models\Employee:private] => 
                    [employee_email:App\Models\Employee:private] => 
                    [employee_created_at:App\Models\Employee:private] => 
                    [employee_updated_at:App\Models\Employee:private] => 
                    [parentRelation:protected] => 
                    [table:protected] => 
                    [keyType:protected] => int
                    [perPage:protected] => 15
                    [incrementing] => 1
                    [timestamps] => 1
                    [attributes:protected] => Array
                        (
                            [_id] => MongoDB\BSON\ObjectID Object
                                (
                                    [oid] => 586ca8d31a72cb07a6815671
                                )

                            [employee_name] => Carlos
                            [employee_description] => test description
                            [employee_email] => carlos@email.com
                            [updated_at] => 2017-01-04 11:45:20
                            [created_at] => 2017-01-04 11:45:20
                        )

                    [original:protected] => Array
                        (
                            [_id] => MongoDB\BSON\ObjectID Object
                                (
                                    [oid] => 586ca8d31a72cb07a6815671
                                )

                            [employee_name] => Carlos
                            [employee_description] => test description
                            [employee_email] => carlos@email.com
                            [updated_at] => 2017-01-04 11:45:20
                            [created_at] => 2017-01-04 11:45:20
                        )

                    [relations:protected] => Array
                        (
                            [tasks] => Illuminate\Database\Eloquent\Collection Object
                                (
                                    [items:protected] => Array
                                        (
                                        )

                                )

                        )

                    [hidden:protected] => Array
                        (
                        )

                    [visible:protected] => Array
                        (
                        )

                    [appends:protected] => Array
                        (
                        )

                    [fillable:protected] => Array
                        (
                        )

                    [guarded:protected] => Array
                        (
                            [0] => *
                        )

                    [dates:protected] => Array
                        (
                        )

                    [dateFormat:protected] => 
                    [casts:protected] => Array
                        (
                        )

                    [touches:protected] => Array
                        (
                        )

                    [observables:protected] => Array
                        (
                        )

                    [with:protected] => Array
                        (
                        )

                    [exists] => 1
                    [wasRecentlyCreated] => 
                )

        )

)

在输出中,关系任务项为空。

谁能告诉我 b/w collection 关系是正确的吗?

Update

我在关系中使用了 belongsToMany。现在我的模型是:

在员工模型中:

    public function tasks()
    {
        return $this->belongsToMany('App\Models\Task');
    }

在任务模型中:

    public function employees()
    {
        return $this->belongsToMany('App\Models\Employee');
    }

这些是文档:

员工collection

{
    "_id" : ObjectId("586ca8c71a72cb07a681566d"),
    "employee_name" : "Carlos",
    "employee_description" : "test description",
    "employee_email" : "carlos@email.com",
    "updated_at" : "2017-01-04 11:45:20",
    "created_at" : "2017-01-04 11:45:20",
    "task_ids" : [ 
        ObjectId("586ccbcf1a72cb07a6815b04"), 
        ObjectId("586cd3261a72cb07a6815c69")
    ]
}, 
{
    "_id" : ObjectId("586ca8d31a72cb07a6815671"),
    "employee_name" : "John",
    "employee_description" : "test description",
    "employee_email" : "john@email.com",
    "updated_at" : "2017-01-04 11:45:20",
    "created_at" : "2017-01-04 11:45:20"
}

任务collection

{
    "_id" : ObjectId("586ccbcf1a72cb07a6815b04"),
    "task_name" : "New Task",
    "task_description" : "test description",
    "task_status" : 1,
    "task_start" : "2017-04-01 12:00:00",
    "task_end" : "2017-04-01 02:00:00",
    "task_created_at" : "2017-04-01 02:17:00",
    "task_updated_at" : "2017-04-01 02:17:00",
    "employee_ids" : [ 
        ObjectId("586ca8c71a72cb07a681566d"), 
        ObjectId("586ca8d31a72cb07a6815671")
    ]
},
{
    "_id" : ObjectId("586cd3261a72cb07a6815c69"),
    "task_name" : "2nd Task",
    "task_description" : "test description",
    "task_status" : 1,
    "task_start" : "2017-04-01 12:00:00",
    "task_end" : "2017-04-01 02:00:00",
    "task_created_at" : "2017-04-01 02:17:00",
    "task_updated_at" : "2017-04-01 02:17:00",
    "employee_ids" : ObjectId("586ca8c71a72cb07a681566d")
}

我找到了第一个员工并提供了这些文件:

$employee = Employee::with('tasks')->first();
dd($employee);

我得到了空关系的输出:

Employee {#176
  #connection: "mongodb"
  #collection: "employee"
  #primaryKey: "_id"
  -employee_id: null
  -employee_name: null
  -employee_description: null
  -employee_email: null
  -employee_created_at: null
  -employee_updated_at: null
  #parentRelation: null
  #table: null
  #keyType: "int"
  #perPage: 15
  +incrementing: true
  +timestamps: true
  #attributes: array:10 [
    "_id" => ObjectID {#170}
    "employee_name" => "Carlos"
    "employee_description" => "test description"
    "employee_email" => "carlos@email.com"
    "updated_at" => "2017-01-04 11:45:20"
    "created_at" => "2017-01-04 11:45:20"
    "task_ids" => array:2 [
      0 => ObjectID {#174}
      1 => ObjectID {#175}
    ]
  ]
  #original: array:10 [
    "_id" => ObjectID {#170}
    "employee_name" => "Carlos"
    "employee_description" => "test description"
    "employee_email" => "carlos@email.com"
    "updated_at" => "2017-01-04 11:45:20"
    "created_at" => "2017-01-04 11:45:20"
    "task_ids" => array:2 [
      0 => ObjectID {#174}
      1 => ObjectID {#175}
    ]
  ]
  #relations: array:1 [
    "tasks" => Collection {#173
      #items: []
    }
  ]
  #hidden: []
  #visible: []
  #appends: []
  #fillable: []
  #guarded: array:1 [
    0 => "*"
  ]
  #dates: []
  #dateFormat: null
  #casts: []
  #touches: []
  #observables: []
  #with: []
  +exists: true
  +wasRecentlyCreated: false
}

我从你的另一个问题中了解到,一个任务可以属于多个员工,对吧?所以你应该在你的 Task 模型中使用 belongsToMany 关系。此外,您的示例 "task" 集合显示在一个文档中 employee_id 是一个数组,而在另一个文档中它是一个 ObjectId,而两者都应该是数组。

无论如何,我很难弄清楚这一点,但我看到你不能使用 hasMany 作为 belongsToMany 的反函数,因为 belongsToMany 创建一个 id 数组,而 hasMany 不适用于数组。我会说我们需要类似 hasManyInArray 的东西,但是当我关联 belongsToMany 关系时,"parent" 文档会创建一个 id 数组,这让我认为父级应该也使用 belongsToMany,即使它不是 "belong to" 但实际上是 "has"。因此,当您将员工与这样的任务相关联时:

$task->employees()->save($employee);

"employee" 文档最终将有一个 "task_ids" 属性,它应该有唯一的任务 ID。所以这似乎是 Jenssegers 的方式:在两个模型中使用 belongsToMany

Laravel:型号:员工:

<?php
namespace App\Models;

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class Employee extends Eloquent
{
    protected $collection = 'employee';

    public function tasks()
    {
        return $this->belongsToMany(Task::class);
    }
}

Laravel:模型:任务:

<?php
namespace App\Models;

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class Task extends Eloquent
{
    protected $collection = 'task';

    public function employees()
    {
        return $this->belongsToMany(Employee::class);
    }
}

你会这样使用:

// Give a task a new employee
$task->employees()->save($employee);

// Or give an employee a new task
$employee->tasks()->save($task);

唯一的问题是,当您查看数据库时,您会看到您的员工文档有一个名为 "task_ids" 的数组,其中包含每个员工唯一的任务 ID。希望对您有所帮助。


只是一些旁注,您知道不必在每个模型上定义主键的名称,对吗?你不需要这个:

protected $primaryKey = '_id';

此外,您不必定义集合的名称(即 protected $collection = 'employee';),除非您真的希望它们是单数形式(默认情况下它们是复数形式)。


我半夜起床(这里是 3:52AM),在电脑上查了一些东西,然后查了 SO,看到了你的问题,我希望这次我能尽快回答你,我们似乎在不同的时区。

Update

这些是我为测试创建的文档:

员工合集

{
    "_id" : ObjectId("5870ba1973b55b03d913ba54"),
    "name" : "Jon",
    "updated_at" : ISODate("2017-01-07T09:51:21.316Z"),
    "created_at" : ISODate("2017-01-07T09:51:21.316Z"),
    "task_ids" : [ 
        "5870ba1973b55b03d913ba56"
    ]
},
{
    "_id" : ObjectId("5870ba1973b55b03d913ba55"),
    "name" : "Doe",
    "updated_at" : ISODate("2017-01-07T09:51:21.317Z"),
    "created_at" : ISODate("2017-01-07T09:51:21.317Z"),
    "task_ids" : [ 
        "5870ba1973b55b03d913ba56"
    ]
}

任务合集

{
    "_id" : ObjectId("5870ba1973b55b03d913ba56"),
    "name" : "New Task",
    "updated_at" : ISODate("2017-01-07T09:51:21.317Z"),
    "created_at" : ISODate("2017-01-07T09:51:21.317Z"),
    "employee_ids" : [ 
        "5870ba1973b55b03d913ba54", 
        "5870ba1973b55b03d913ba55"
    ]
}

有了这些文件,我得到了这样的第一个员工:

$employee = Employee::with('tasks')->first();
dd($employee);

并且在输出中我们可以看到 relations 属性是一个数组:

Employee {#186 ▼
  #collection: "employee"
  #primaryKey: "_id"
  // Etc.....
  #relations: array:1 [▼
    "tasks" => Collection {#199 ▼
      #items: array:1 [▼
        0 => Task {#198 ▼
          #collection: "task"
          #primaryKey: "_id"
          // Etc....
          #attributes: array:5 [▼
            "_id" => ObjectID {#193}
            "name" => "New Task"
            "updated_at" => UTCDateTime {#195}
            "created_at" => UTCDateTime {#197}
            "employee_ids" => array:2 [▶]
          ]
        }
      ]
    }
  ]
}

Update 2

belongsToMany 方法不在您提到的文件中,因为 class(即 Jenssegers\Mongodb\Eloquent\Model)扩展了 Laravel 的 Eloquent 模型 class,这就是 belongsToMany 方法所在的位置。

好的,这一定是它对您不起作用的原因,因为数组必须是字符串而不是 ObjectId。为什么是这样?因为这就是 Jenssegers 库的工作方式,所以它将 ID 保存为字符串。我也发现这种行为很奇怪,但这就是它的工作原理。请记住,您应该 使用 Jenssegers 库关联对象,而不是通过在数据库中手动创建数据。 你如何索引ID?只需在 MongoDB 中创建一个普通索引,例如 tasks.createIndex({task_ids: 1})。这是关于如何创建索引的文档:https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/. You can also create indexes on migrations, here are the docs on migrations, make sure to read Jenssegers notes on migrations 也是。

您可以像这样访问 tasks 领域:$employee->tasks;。您通过获取与您声明关系的方法同名的 属性 来访问关系,因此如果您有:

class Post
{
    public function owner()
    {
        return $this->belongsTo(User::class);
    }
}

你得到的关系是 $post->owner;。这是关于关系的文档:https://laravel.com/docs/5.3/eloquent-relationships