MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

La libreria Laravel MongoDB 'jensegers/laravel-mongodb' ha molte relazioni non funzionanti

Ho capito dall'altra tua domanda, che un compito può appartenere a molti dipendenti, giusto? Quindi dovresti usare belongsToMany relazione nella tua Task modello. Anche la tua raccolta di "attività" di esempio mostra che in un documento employee_id è un array e nell'altro documento è un ObjectId, quando entrambi dovrebbero essere array.

Ad ogni modo, ho avuto difficoltà a cercare di capirlo, ma ho visto che non puoi usare hasMany come l'inverso di belongsToMany , perché belongsToMany crea una matrice di ID e hasMany non funziona bene con gli array. Direi che avremmo bisogno di qualcosa come hasManyInArray , ma quando associo un belongsToMany relazione, il documento "genitore" viene creato un array di ID, il che mi porta a pensare che anche il genitore dovrebbe usare belongsToMany anche se non "appartiene" ma in realtà "ha". Quindi, quando assoceresti un dipendente a un'attività come questa:

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

Il documento "employee" finirà per avere un attributo "task_ids" con l'unico ID attività che dovrebbe avere. Quindi questa sembra essere la strada da percorrere con Jenssegers:usare belongsToMany in entrambi i modelli:

Laravel:Modello:Impiegato:

<?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:Modello:Compito:

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

E useresti questo come:

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

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

L'unica cosa è che quando guardi il database, vedrai che i documenti dei tuoi dipendenti hanno un array chiamato "task_ids" e al suo interno, l'id dell'unica attività che ogni dipendente ha. Spero che questo ha aiutato.

Solo alcune note a margine, sai che non devi definire il nome della chiave primaria su ogni modello, giusto? Non hai bisogno di questo:

protected $primaryKey = '_id';

Inoltre non è necessario definire il nome della collezione (es. protected $collection = 'employee'; ), a meno che tu non voglia davvero che siano al singolare (per impostazione predefinita sono al plurale).

Mi sono alzato nel cuore della notte (sono le 3:52 qui) e ho controllato qualcosa sul computer e poi ho controllato SO e ho visto la tua domanda, spero che questa volta abbia risposto abbastanza presto per te, sembra che siamo in fusi orari diversi.

Questi sono i documenti che ho creato per il test:

raccolta dipendenti

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

raccolta attività

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

Con questi documenti ottengo il primo dipendente così:

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

E nell'output possiamo vedere che l'attributo delle relazioni è un array:

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

Il belongsToMany il metodo non è nel file che menzioni perché quella classe (cioè Jenssegers\Mongodb\Eloquent\Model ) estende la classe Eloquent Model di Laravel, ed è qui che belongsToMany metodo è.

Ok, questo deve essere il motivo per cui non funziona per te, perché gli array devono essere stringhe anziché ObjectIds. Perchè è questo? Perché è così che funziona la libreria Jenssegers, salva gli ID come stringhe. Ho anche trovato strano questo comportamento, ma è così che funziona. Ricorda che dovresti per mettere in relazione gli oggetti usando la libreria Jenssegers, non creando i dati manualmente nel database. Come puoi indicizzare gli ID? Basta creare un indice normale in MongoDB, come tasks.createIndex({task_ids: 1}) . Ecco la documentazione su come creare indici:https://docs .mongodb.com/manual/reference/method/db.collection.createIndex/ . Puoi anche creare indici sulle migrazioni, ecco i documenti sulle migrazioni , assicurati di leggere le Note Jenssegers sulle migrazioni anche.

Puoi accedere alle Task realtion in questo modo:$employee->tasks; . Accedi alle relazioni ottenendo una proprietà con lo stesso nome del metodo con cui hai dichiarato la tua relazione, quindi se hai:

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

Ottieni la relazione come $post->owner; . Ecco la documentazione sulle relazioni:https://laravel.com/docs/5.3/eloquent-relationships