Laravel MongoDB库'jenssegers / laravel-mongodb'有很多关系不起作用

时间:2017-01-07 07:12:43

标签: mongodb laravel orm laravel-5.3 jenssegers-mongodb

我在version 3.1.0-alpha中使用MongoDB库https://github.com/jenssegers/laravel-mongodb Laravel 5.3.28我在MongoDB中有两个集合,我想与它们建立一个hasMany关系。意味着每个员工执行许多任务。我在任务集合中使用了引用并添加了employee_ids。

以下是我的代码:

MongoDB的:

第一次收集:员工

{
    "_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"
}

第二次收集:任务

{
    "_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集合是否正确?

  

更新

我使用了belongsToManyin的关系。现在我的模特是:

在员工模型中:

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

在任务模型中:

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

这些是文件:

员工收集

{
    "_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"
}

任务集合

{
    "_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
}

1 个答案:

答案 0 :(得分:2)

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

无论如何,我很难想出来,但我发现你不能使用hasMany作为belongsToMany的倒数,因为belongsToMany创建一个id数组,hasMany不适用于数组。我会说我们需要类似hasManyInArray的东西,但是当我关联belongsToMany关系时,“父”文档会被创建一个id数组,这让我认为父类也应该使用belongsToMany即使它不“属于”但实际上“有”。因此,当您将员工与此类任务相关联时:

$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点52分)并检查了电脑上的东西然后检查了所以看到了你的问题,我希望这次我很快回答你,我们似乎在不同的时区。

  

更新

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

员工集合

{
    "_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 [▶]
          ]
        }
      ]
    }
  ]
}
  

更新2

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

好的,这就是为什么它不适合你,因为数组必须是字符串而不是ObjectIds。为什么是这样?因为这就是Jenssegers库的工作方式,它将Ids保存为字符串。我也发现这种行为很奇怪,但这就是它的工作原理。请记住,应该使用Jenssegers库关联对象,而不是通过在数据库中手动创建数据。 你如何索引ID?只需在MongoDB中创建一个普通索引,如tasks.createIndex({task_ids: 1})。以下是有关如何创建索引的文档:https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/。您还可以在迁移here are the docs on migrations上创建索引,请务必阅读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