MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Laravel MongoDB библиотека 'jenssegers/laravel-mongodb' hasMany връзка не работи

От другия ви въпрос разбрах, че една задача може да принадлежи на много служители, нали? Така че трябва да използвате belongsToMany връзка във вашата Task модел. Също така вашата примерна колекция от „задачи“ показва, че в един документ employee_id е масив, а в другия документ е ObjectId, когато и двете трябва да са масиви.

Както и да е, трудно се опитах да разбера това, но видях, че не можете да използвате hasMany като обратното на belongsToMany , защото belongsToMany създава масив от идентификатори и hasMany не работи добре с масиви. Бих казал, че ще ни трябва нещо като hasManyInArray , но когато асоциирам belongsToMany връзка, документът "родител" се създава масив от идентификатори, което ме кара да мисля, че родителят също трябва да използва belongsToMany въпреки че не „принадлежи на“, а всъщност „има“. Така че, когато свържете служител със задача като тази:

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

Документът "служител" в крайна сметка ще има атрибут "task_ids" с единствения идентификатор на задача, който трябва да има. Така че изглежда това е начинът да вървим с 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“, а вътре в него идентификаторът на единствената задача, която всеки служител има. Надявам се, че това помогна.

Само някои странични бележки, знаете, че не е нужно да дефинирате името на първичния ключ на всеки модел, нали? Нямате нужда от това:

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);

И в изхода можем да видим, че атрибутът на релациите е масив:

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

belongsToMany методът не е във файла, който споменавате, защото този клас (т.е. Jenssegers\Mongodb\Eloquent\Model ) разширява класа Eloquent Model на Laravel и това е мястото, където belongsToMany метод е.

Добре, така че това трябва да е причината, поради която не работи за вас, защото масивите трябва да бъдат низове вместо ObjectIds. Защо е това? Тъй като библиотеката на Jenssegers работи така, тя записва идентификаторите като низове. Също така намирам това поведение за странно, но така работи. Не забравяйте, че се предполага за свързване на обекти с помощта на библиотеката на Jenssegers, а не чрез създаване на данните ръчно в базата данни. Как можете да индексирате идентификаторите? Просто създайте нормален индекс в MongoDB, като tasks.createIndex({task_ids: 1}) . Ето документацията за създаване на индекси:https://docs .mongodb.com/manual/reference/method/db.collection.createIndex/ . Можете също да създавате индекси за миграции, ето документите за миграции , не забравяйте да прочетете бележките на Jenssegers относно миграциите също.

Имате достъп до tasks реалност като тази:$employee->tasks; . Вие осъществявате достъп до релации, като получите свойство със същото име на метода, с който сте декларирали релацията си, така че ако имате:

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

Получавате релацията като $post->owner; . Ето документацията за отношенията:https://laravel.com/docs/5.3/eloquent-relationships




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Намиране на всички записи, съдържащи дадено подполе в mongodb

  2. По-добър начин за преместване на MongoDB колекция в друга колекция

  3. Как да комбинирате използването на оператора all и icontains за mongoengine

  4. MongoDB c# извлича всички съответстващи елементи в масив в рамките на документ с помощта на Definition builder

  5. Как да изберете едно поле в MongoDB с помощта на Pymongo?