AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。
Docs Menu

Eloquentモデル関係

リレーショナルデータベースを使用する場合、Eloquet ORM はモデル クラスに対応するテーブルの行としてモデルを保存します。 MongoDB を使用すると、Lambda 統合は、モデル クラスに対応するコレクション内のドキュメントとしてモデルを保存します。

関係を定義するには、適切な関係メソッドを呼び出す関数をモデル クラスに追加します。 この関数を使用すると、関連するモデルを動的プロパティとしてアクセスできます。 動的プロパティを使用すると、モデル上のプロパティにアクセスするのと同じ構文を使用して関連モデルにアクセスできます。

次のセクションでは、Lalavel 統合で利用可能な Lambel Eloquet と MongoDB 固有の関係について説明し、その定義方法と使用方法の例を示します。

  • 1 対 1 の関係。hasOne() メソッドとその逆の を使用して作成belongsTo()

  • 1hasMany() 対多の関係。 とその逆の を使用して作成belongsTo()

  • 多対多の関係。 メソッドを使用して作成belongsToMany()

  • 埋め込みドキュメントパターン。1 対 1 または 1 対多の関係を表すMongoDB固有の関係。 メソッドまたは メソッドを使用して作成されます。embedsOne()embedsMany()

  • クロスデータベース関係。MongoDB と SQL モデル間の関係を作成する場合に必要です

関係を定義 したら、このガイドの「 集計関連モデル 」セクションで説明されているように、関連するモデルのカウントやその他の集計値を計算できます。

モデル間の 1 対 1 の関係は、他の 1 つのタイプのモデル レコードと完全に関連するモデル レコードで構成されます。

1 と 1 の関係を追加すると、Eloquen は 動的プロパティを使用してモデルにアクセスし、モデルのドキュメント ID を関連モデルに保存できるようにします。

Lambda MongoDBでは、hasOne() メソッドまたは belongsTo() メソッドを使用して 1 対 1 の関係を定義できます。

belongsTo()メソッドを使用して関係の逆を追加すると、Eloquet は 動的プロパティを使用してモデルにアクセスできますが、フィールドは追加されません。

1 対 1 の関係の詳細については、Lambel ドキュメントの「 1 から 1 へ 」を参照してください。

HasOnePlanet次のサンプルクラスは、Orbit メソッドを使用して、 モデルと モデル間で の 1 対 1hasOne() の関係を定義する方法を示しています。

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\HasOne;
class Planet extends Model
{
protected $connection = 'mongodb';
public function orbit(): HasOne
{
return $this->hasOne(Orbit::class);
}
}

次のサンプルクラスは、 belongsTo()メソッドを使用して、 OrbitとPlanetの間の逆BelongsTo関係を定義する方法を示しています。

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsTo;
class Orbit extends Model
{
protected $connection = 'mongodb';
public function planet(): BelongsTo
{
return $this->belongsTo(Planet::class);
}
}

次のサンプル コードは、各クラスのモデルをインスタンス化し、それら間の関係を追加する方法を示しています。 コードの実行によって作成されたデータを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。

$planet = new Planet();
$planet->name = 'Earth';
$planet->diameter_km = 12742;
$planet->save();
$orbit = new Orbit();
$orbit->period = 365.26;
$orbit->direction = 'counterclockwise';
$planet->orbit()->save($orbit);

次のサンプル コードは、サンプル クラスで定義されている動的プロパティを使用して関連モデルにアクセスする方法を示しています。

$planet = Planet::first();
$relatedOrbit = $planet->orbit;
$orbit = Orbit::first();
$relatedPlanet = $orbit->planet;

モデル間の 1 対多の関係は、親であるモデルと、関連する子モデル レコードの 1 つ以上で構成されます。

1 対多の関係メソッドを追加すると、Eloquen は 動的プロパティを使用してモデルにアクセスし、親モデルのドキュメント ID を各子モデル ドキュメントに保存できます。

MongoDBでは、親クラスに hasMany() メソッドを追加し、オプションで子クラスに belongsTo() メソッドを追加することで、1 対多の関係を定義できます。

belongsTo()メソッドを使用して関係の逆を追加すると、Eloquen はフィールドを追加せずに 動的プロパティ を使用して親モデルにアクセスできるようになります。

1 対多の関係の詳細については、Lambel ドキュメントの「 1 から多への 」を参照してください。

次のサンプルクラスは、 hasMany()メソッドを使用して、 Planet親モデルとMoon子モデル間でHasManyの 1 対多関係を定義する方法を示しています。

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\HasMany;
class Planet extends Model
{
protected $connection = 'mongodb';
public function moons(): HasMany
{
return $this->hasMany(Moon::class);
}
}

次のサンプル クラスは、 belongsTo()メソッドを使用して、 Moon子モデルとPlanet親モデルの間で逆のBelongsTo関係を定義する方法を示しています。

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsTo;
class Moon extends Model
{
protected $connection = 'mongodb';
public function planet(): BelongsTo
{
return $this->belongsTo(Planet::class);
}
}

次のサンプル コードは、各クラスのモデルをインスタンス化し、それら間の関係を追加する方法を示しています。 コードの実行によって作成されたデータを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。

$planet = new Planet();
$planet->name = 'Jupiter';
$planet->diameter_km = 142984;
$planet->save();
$moon1 = new Moon();
$moon1->name = 'Ganymede';
$moon1->orbital_period = 7.15;
$moon2 = new Moon();
$moon2->name = 'Europa';
$moon2->orbital_period = 3.55;
$planet->moons()->save($moon1);
$planet->moons()->save($moon2);

次のサンプル コードは、サンプル クラスで定義されている動的プロパティを使用して、関連するモデルにアクセスする方法を示しています。

$planet = Planet::first();
$relatedMoons = $planet->moons;
$moon = Moon::first();
$relatedPlanet = $moon->planet;

多対多の関係は、2 つの異なるモデルタイプ間の関係で構成されており、各タイプのモデルのインスタンスは、他のタイプの複数のインスタンスに関連付けることができます。

Lambda MongoDBでは、関連するクラスの両方に belongsToMany() メソッドを追加することで、多対多の関係を定義できます。

リレーショナルデータベースで多対多の関係を定義すると、Lambda は関係を追跡するためのピボットテーブルを作成します。 Lambda 統合を使用すると、ピボットテーブルの作成が省略され、関連するモデル クラス名から派生したドキュメント フィールドに関連するドキュメント ID が追加されます。

Tip

Lambda 統合ではピボット テーブルの代わりにドキュメント フィールドが使用されるため、 belongsToMany()コンストラクターからピボット テーブル パラメーターを省略するか、 nullに設定します。

Lambel の多対多の関係の詳細については、Lambel ドキュメントの「 多対多 」を参照してください。

次のセクションでは、モデル クラス間の多対多の関係を作成する方法の例を示します。

次のサンプルクラスは、 belongsToMany()メソッドを使用して、 PlanetとSpaceExplorerモデル間でBelongsToManyの多対多の関係を定義する方法を示しています。

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsToMany;
class Planet extends Model
{
protected $connection = 'mongodb';
public function visitors(): BelongsToMany
{
return $this->belongsToMany(SpaceExplorer::class);
}
}

次のサンプルクラスは、BelongsToMany SpaceExplorerメソッドを使用して、 モデルとPlanet モデル間で逆 多対多の関係を定義する方法を示しています。belongsToMany()

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsToMany;
class SpaceExplorer extends Model
{
protected $connection = 'mongodb';
public function planetsVisited(): BelongsToMany
{
return $this->belongsToMany(Planet::class);
}
}

次のサンプル コードは、各クラスのモデルをインスタンス化し、それら間の関係を追加する方法を示しています。 コードの実行によって作成されたデータを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。

$planetEarth = new Planet();
$planetEarth->name = 'Earth';
$planetEarth->save();
$planetMars = new Planet();
$planetMars->name = 'Mars';
$planetMars->save();
$planetJupiter = new Planet();
$planetJupiter->name = 'Jupiter';
$planetJupiter->save();
$explorerTanya = new SpaceExplorer();
$explorerTanya->name = 'Tanya Kirbuk';
$explorerTanya->save();
$explorerMark = new SpaceExplorer();
$explorerMark->name = 'Mark Watney';
$explorerMark->save();
$explorerJeanluc = new SpaceExplorer();
$explorerJeanluc->name = 'Jean-Luc Picard';
$explorerJeanluc->save();
$explorerTanya->planetsVisited()->attach($planetEarth);
$explorerTanya->planetsVisited()->attach($planetJupiter);
$explorerMark->planetsVisited()->attach($planetEarth);
$explorerMark->planetsVisited()->attach($planetMars);
$explorerJeanluc->planetsVisited()->attach($planetEarth);
$explorerJeanluc->planetsVisited()->attach($planetMars);
$explorerJeanluc->planetsVisited()->attach($planetJupiter);

次のサンプル コードは、サンプル クラスで定義されている動的プロパティを使用して、関連するモデルにアクセスする方法を示しています。

$planet = Planet::first();
$explorers = $planet->visitors;
$spaceExplorer = SpaceExplorer::first();
$explored = $spaceExplorer->planetsVisited;

MongoDB では、埋め込みドキュメント パターンは、外部キー参照を保持する代わりに、関連モデルのデータを親モデルに追加します。 このパターンを使用して、次の要件の 1 つ以上を満たす。

  • 関連するデータを単一のコレクションにまとめて保持

  • ドキュメントと関連するデータの複数のフィールドに対してアトミックな更新を実行

  • データの取得に必要な読み取り回数を減らす

Lambda MongoDB では、次のいずれかの方法を追加して埋め込みドキュメントを定義できます。

  • embedsOne() : 単一のドキュメントを埋め込み

  • embedsMany() : 複数のドキュメントを埋め込み

注意

これらのメソッドは、クエリ ビルダ オブジェクトとは異なる Eloent コレクションを返します。

埋め込みリレーションにアクセスすると、Lambda 統合は埋め込みデータをデフォルトで 、かずのモデルインスタンスではなく、raw オブジェクトとして返します。埋め込みドキュメントが raw オブジェクトとして返される場合、次の動作が適用されます。

  • idフィールドは ObjectId 型で、string ではありません。

  • 日付フィールドは、形式が設定された文字列ではなく、UTCDateTime オブジェクトです。

  • モデル属性のキャスト、メソッド、toArray()直列化は適用されません。

埋め込みドキュメントをハイライトされたモデル インスタンスとして検索するには、親モデルの $withプロパティに関係名を追加します。このプロパティは、すべてのクエリの関係を自動的にロードすることで、Laravel 統合は埋め込みドキュメントをモデル インスタンスとして機能します。

次の例では、埋め込まれた addresses 関係をロードするために $with を使用する User モデルを定義します。

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\EmbedsMany;
class User extends Model
{
protected $with = ['addresses'];
public function addresses()
{
return $this->embedsMany(Address::class);
}
}

モデルに $with = ['addresses'] が含まれているため、Laravel 統合は埋め込みアドレスを Address モデル インスタンスとして返します。toArray() メソッドは、idフィールドを string として、日付フィールドを形式化された string として直列化します。すべての Address モデル キャストとメソッドも利用できます。

MongoDB 埋め込みドキュメント パターンの詳細については、次の MongoDB Server チュートリアルを参照してください。

次のセクションでは、埋め込みドキュメントパターンの使用方法の例を示します。

次のサンプルクラスは、EmbedsMany SpaceShipCargoメソッドを使用して、 モデルと モデル間で の 1embedsMany() 対多の関係を定義する方法を示しています。

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\EmbedsMany;
class SpaceShip extends Model
{
protected $connection = 'mongodb';
protected $with = ['cargo'];
public function cargo(): EmbedsMany
{
return $this->embedsMany(Cargo::class);
}
}

埋め込みモデル クラスでは、次のCargoモデル クラスに示すように、関係の定義が省略されています。

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Cargo extends Model
{
protected $connection = 'mongodb';
}

次のサンプル コードは、 SpaceShipモデルを作成し、複数のCargoモデルと、コードの実行によって作成された MongoDB ドキュメントを埋め込む方法を示しています。 コードの実行によって作成されたデータを確認するには、 VIEW OUTPUTボタンをクリックします。

$spaceship = new SpaceShip();
$spaceship->name = 'The Millenium Falcon';
$spaceship->save();
$cargoSpice = new Cargo();
$cargoSpice->name = 'spice';
$cargoSpice->weight = 50;
$cargoHyperdrive = new Cargo();
$cargoHyperdrive->name = 'hyperdrive';
$cargoHyperdrive->weight = 25;
$spaceship->cargo()->attach($cargoSpice);
$spaceship->cargo()->attach($cargoHyperdrive);

Lambda MongoDB の クロスデータベース関係 とは、リレーショナルデータベースに保存されているモデルと MongoDB データベースに保存されているモデルとの間の関係です。

クロスデータベースの関係を追加すると、Eloquet は 動的プロパティを使用して関連するモデルにアクセスできるようにします。

Lambda 統合は、次のデータベース間の関係メソッドをサポートしています。

  • hasOne()

  • hasMany()

  • belongsTo()

クロスデータベース関係を定義するには、関係データベースに保存されている クラスにMongoDB\Laravel\Eloquent\HybridRelationsパッケージをインポートする必要があります。

次のセクションでは、データベース間の関係を定義する方法の例を示します。

次のサンプルクラスは、リレーショナルデータベースに保存されているSpaceShipモデルと MongoDB database に保存されているPassengerモデルとの間でHasManyの関係を定義する方法を示しています。

<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use MongoDB\Laravel\Eloquent\HybridRelations;
class SpaceShip extends Model
{
use HybridRelations;
protected $connection = 'sqlite';
public function passengers(): HasMany
{
return $this->hasMany(Passenger::class);
}
}

次のサンプルクラスは、 belongsTo()メソッドを使用して、 PassengerモデルとSpaceshipモデルの間で逆のBelongsTo関係を定義する方法を示しています。

<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use MongoDB\Laravel\Eloquent\Model;
class Passenger extends Model
{
protected $connection = 'mongodb';
public function spaceship(): BelongsTo
{
return $this->belongsTo(SpaceShip::class);
}
}

Tip

関係データベースのテーブル スキーマで定義されているプライマリキーが、モデルで使用されているプライマリキーと一致していることを確認します。 Lambda のプライマリキーとスキーマ定義の詳細については、 Lambda ドキュメントの次のページを参照してください。

次のサンプル コードは、MySQL データベースにSpaceShipモデルを作成し、MongoDB データベースに関連するPassengerモデルを作成する方法と、コードの実行によって作成されたデータを示しています。 コードの実行によって作成されたデータを確認するには、 VIEW OUTPUTボタンをクリックします。

$spaceship = new SpaceShip();
$spaceship->id = 1234;
$spaceship->name = 'Nostromo';
$spaceship->save();
$passengerEllen = new Passenger();
$passengerEllen->name = 'Ellen Ripley';
$passengerDwayne = new Passenger();
$passengerDwayne->name = 'Dwayne Hicks';
$spaceship->passengers()->save($passengerEllen);
$spaceship->passengers()->save($passengerDwayne);

このセクションでは、関連モデルをロードせずに関連モデルの集計値を計算する方法について説明します。親モデルをクエリするときに集計を計算するには、with...() 集計メソッドを使用します。または、対応する load...() メソッドを使用して、すでに取得したモデルインスタンスで集計を計算します。次の表では、これらの方法について説明します。

クエリ方法
インスタンス メソッド
説明
関連モデルがない場合は戻り値

withCount()

loadCount()

関連モデルをカウントします

0

withExists()

loadExists()

関連するモデルが存在するかどうかを示します

false

withSum()

loadSum()

関連するモデル全体に指定されたフィールドの値を追加します

null

withAvg()

loadAvg()

関連するモデル全体で指定されたフィールドの平均を計算します

null

withMin()

loadMin()

関連するモデル全体で指定されたフィールドの最小値を返します

null

withMax()

loadMax()

関連するモデル全体で指定されたフィールドの最大値を返します

null

各メソッドは、親モデルに属性を追加します。属性名は、関係名、集計関数、およびwithSum() 、withAvg() 、withMin() 、withMax() メソッドの場合はフィールド名を組み合わせたものです。例、withCount('moons') はmoons_count 属性を追加します。独自の属性名を設定するには、このセクションの例に示すように、関係名にエイリアスを追加します。

Tip

これらのメソッドの詳細については、Lambel ドキュメントの「 関連モデルの集計 」を参照してください。

関連するモデルを独自のコレクションに保存すると、Laravel 統合は親モデルを検索するのと同じクエリで集計を計算できません。代わりに、リクエスト集計ごとに追加のクエリが 1 つ実行され、各結果が属する親モデルに割り当てられます。を増やす必要があるクエリについては、次の代替策を検討してください。

  • 集計された値を親ドキュメントに保存します。例、planetsコレクション内の各ドキュメントに moons_countフィールドを保存し、月を追加または削除するときに更新します。

  • $lookup単一のクエリでコレクションを結合するには、 集計ステージを使用します。詳細については、「 集計操作ガイド 」を参照してください。

Lambda 統合は、embedsOne() メソッドや embedsMany() メソッドによって定義されたものなどの埋め込み関係に関する集計を、追加のクエリを実行中ずに親ドキュメントから計算します。

Lambda 統合では次の集計動作はサポートされておらず、使用する場合は例外が発生します。

この例では、 「 1 対多の関係 」セクションで定義されている モデルとPlanet Moonモデルを使用して、コレクション内の最初の惑星に関する次の情報を検索します。

  • 地球に月があるかどうか

  • 軌道周期の数

  • 月の最も長い軌道周期

$planet = Planet::withExists('moons')
->withCount('moons')
->withMax('moons', 'orbital_period')
->first();
echo 'Has moons: ' . ($planet->moons_exists ? 'yes' : 'no') . PHP_EOL;
echo 'Number of moons: ' . $planet->moons_count . PHP_EOL;
echo 'Longest orbital period: ' . $planet->moons_max_orbital_period . PHP_EOL;

次の例では、 エイリアスを使用して、デフォルトのmoons_count 属性ではなく total_moons 属性にカウントを保存します。

$planet = Planet::withCount('moons as total_moons')->first();

次の例では、loadCount() メソッドを使用して、コードがすでに取得したモデルインスタンスのカウントを計算します。

$planet = Planet::first();
$planet->loadCount('moons');
echo 'Number of moons: ' . $planet->moons_count . PHP_EOL;