MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Die Laravel MongoDB-Bibliothek ‚jenssegers/laravel-mongodb‘ hasMany-Beziehung funktioniert nicht

Ich habe durch Ihre andere Frage verstanden, dass eine Aufgabe vielen Mitarbeitern gehören kann, oder? Sie sollten also belongsToMany verwenden Beziehung in Ihrer Task Modell. Auch Ihre beispielhafte „Task“-Sammlung zeigt das in einem Dokument employee_id ist ein Array und im anderen Dokument ist es eine ObjectId, obwohl beide Arrays sein sollten.

Wie auch immer, ich hatte Schwierigkeiten, das herauszufinden, aber ich habe gesehen, dass Sie hasMany nicht verwenden können als Umkehrung von belongsToMany , weil belongsToMany erstellt ein Array von IDs und hasMany funktioniert nicht gut mit Arrays. Ich würde sagen, wir bräuchten so etwas wie hasManyInArray , aber wenn ich einen belongsToMany verknüpfe Beziehung wird das "übergeordnete" Dokument ein Array von IDs erstellt, was mich zu der Annahme veranlasst, dass das übergeordnete Dokument auch belongsToMany verwenden sollte obwohl es nicht „gehört“, sondern eigentlich „hat“. Wenn Sie also einen Mitarbeiter einer Aufgabe wie dieser zuordnen würden:

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

Das „Employee“-Dokument wird am Ende ein „task_ids“-Attribut mit der einzigen Aufgaben-ID haben, die es haben sollte. Das scheint also der richtige Weg für Jenssegers zu sein:belongsToMany zu verwenden in beiden Modellen:

Laravel:Modell:Mitarbeiter:

<?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:Modell:Aufgabe:

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

Und Sie würden dies wie folgt verwenden:

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

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

Das einzige daran ist, dass Sie, wenn Sie sich die Datenbank ansehen, sehen werden, dass Ihre Mitarbeiterdokumente ein Array namens „task_ids“ haben, und darin die ID der einzigen Aufgabe, die jeder Mitarbeiter hat. Ich hoffe, das hat geholfen.

Nur einige Randnotizen, Sie wissen, dass Sie den Namen des Primärschlüssels nicht für jedes Modell definieren müssen, oder? Das brauchen Sie nicht:

protected $primaryKey = '_id';

Außerdem müssen Sie den Namen der Sammlung nicht definieren (z. B. protected $collection = 'employee'; ), es sei denn, Sie möchten wirklich, dass sie im Singular stehen (standardmäßig stehen sie im Plural).

Ich bin mitten in der Nacht aufgestanden (hier ist es 3:52 Uhr) und habe etwas auf dem Computer überprüft und dann SO überprüft und Ihre Frage gesehen. Ich hoffe, ich habe dieses Mal schnell genug für Sie geantwortet, wir scheinen uns in verschiedenen Zeitzonen zu befinden.

Dies sind die Dokumente, die ich zum Testen erstellt habe:

Mitarbeitersammlung

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

Aufgabensammlung

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

Mit diesen Dokumenten bekomme ich den ersten Mitarbeiter so:

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

Und in der Ausgabe sehen wir, dass das relation-Attribut ein Array ist:

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

Der belongsToMany -Methode befindet sich nicht in der von Ihnen erwähnten Datei, da diese Klasse (d. h. Jenssegers\Mongodb\Eloquent\Model ) erweitert die Eloquent Model-Klasse von Laravel, und dort befindet sich belongsToMany Methode ist.

Ok, das muss der Grund sein, warum es bei Ihnen nicht funktioniert, weil die Arrays Zeichenfolgen anstelle von ObjectIds sein müssen. Warum ist das? Denn so funktioniert die Jenssegers-Bibliothek, sie speichert die IDs als Strings. Ich fand dieses Verhalten auch seltsam, aber so funktioniert es. Denken Sie daran, dass Sie sollten um Objekte mit der Jenssegers-Bibliothek zu verknüpfen, nicht durch manuelles Erstellen der Daten in der Datenbank. Wie können Sie die IDs indizieren? Erstellen Sie einfach einen normalen Index in MongoDB, wie tasks.createIndex({task_ids: 1}) . Hier ist die Dokumentation zum Erstellen von Indizes:https://docs .mongodb.com/manual/reference/method/db.collection.createIndex/ . Sie können auch Indizes zu Migrationen erstellen, hier sind die Dokumente zu Migrationen , lesen Sie unbedingt Jenssegers Hinweise zu Migrationen auch.

Sie können auf die tasks zugreifen Beziehung wie folgt:$employee->tasks; . Sie greifen auf Relationen zu, indem Sie eine Eigenschaft mit dem gleichen Namen wie die Methode abrufen, mit der Sie Ihre Relation deklariert haben, also wenn Sie:

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

Sie erhalten die Relation als $post->owner; . Hier ist die Dokumentation zu Beziehungen:https://laravel.com/docs/5.3/eloquent-relationships