文档菜单
文档首页
/ / /
Laravel MongoDB
/

写入操作

本页内容

  • 概述
  • 示例模型
  • 插入文档
  • 插入文档示例
  • 插入多个文档示例
  • 修改文档
  • 更新文档示例
  • 更新多个文档示例
  • 单操作更新或插入
  • Upsert 方法
  • 更新方法
  • 更新文档中的数组
  • 向数组添加值示例
  • 从数组中删除值示例
  • 更新数组元素值示例
  • 删除文档
  • 删除文档示例
  • 删除多个文档示例

在本指南中,您可以学习如何使用Laravel MongoDB在MongoDB集合上执行写入操作。写入操作包括根据指定条件插入、更新和删除数据。

本指南展示了以下任务的执行方法

  • 插入文档

  • 修改文档

  • 删除文档

本指南中的写入操作引用以下Eloquent模型类

Concert.php
<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Concert extends Model
{
protected $connection = 'mongodb';
protected $fillable = ['performer', 'venue', 'genres', 'ticketsSold', 'performanceDate'];
protected $casts = ['performanceDate' => 'datetime'];
}

提示

The$fillable 属性允许您在插入操作中使用Laravel批量赋值。有关批量赋值的更多信息,请参阅自定义批量赋值 在Eloquent模型类文档中。

属性 $casts 指示Laravel将属性转换为常见的数据类型。要了解更多信息,请参阅Laravel文档中的 属性转换

在本节中,您可以了解如何使用Laravel MongoDB将文档插入MongoDB集合。

在插入文档时,请确保数据不违反集合上的任何唯一索引。在插入集合的第一个文档或创建新集合时,MongoDB会自动在 _id 字段上创建唯一索引。

有关使用Laravel架构构建器在MongoDB集合上创建索引的更多信息,请参阅Schema Builder文档中的 管理索引 部分。

有关Laravel集成中Eloquent模型的相关信息,请参阅 Eloquent模型 部分。

以下示例展示了如何使用 save() Eloquent 方法将 Concert 模型实例作为MongoDB文档插入。

save() 方法成功执行时,您可以通过调用该方法的模型实例来访问它。

如果操作失败,模型实例将被分配为null

以下示例代码执行以下操作

  • 创建Concert模型的新实例

  • 将字符串值分配给performervenue字段

  • 将字符串数组分配给genre字段

  • 将数字分配给ticketsSold字段

  • 使用Carbon包将日期分配给performanceDate字段

  • 通过调用save()方法插入文档

通过在实例上调用save()方法插入文档。
$concert = new Concert();
$concert->performer = 'Mitsuko Uchida';
$concert->venue = 'Carnegie Hall';
$concert->genres = ['classical'];
$concert->ticketsSold = 2121;
$concert->performanceDate = Carbon::create(2024, 4, 1, 20, 0, 0, 'EST');
$concert->save();

您可以通过访问模型的id成员来检索插入文档的_id值,如下面的代码示例所示

$insertedId = $concert->id;

如果您通过定义$fillable$guarded属性启用批量赋值,则可以使用Eloquent模型create()方法在一个调用中执行插入,如下面的示例所示

$insertResult = Concert::create([
'performer' => 'The Rolling Stones',
'venue' => 'Soldier Field',
'genres' => [ 'rock', 'pop', 'blues' ],
'ticketsSold' => 59527,
'performanceDate' => Carbon::create(2024, 6, 30, 20, 0, 0, 'CDT'),
]);

有关Carbon PHP API扩展的更多信息,请参阅Carbon GitHub仓库。

此示例演示如何使用Eloquent的insert()方法将多个Concert模型实例作为MongoDB文档插入。此批量插入方法减少了您的应用程序需要调用来保存文档的次数。

insert()方法成功时,它返回值1

如果失败,则抛出异常。

示例代码通过将它们作为数组传递给insert()方法,在单个调用中保存多个模型。

注意

此示例将日期包装在MongoDB\BSON\UTCDateTime类中,以转换为MongoDB可以序列化的类型,因为Laravel在批量插入操作中跳过了属性转换。

$data = [
[
'performer' => 'Brad Mehldau',
'venue' => 'Philharmonie de Paris',
'genres' => [ 'jazz', 'post-bop' ],
'ticketsSold' => 5745,
'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')),
],
[
'performer' => 'Billy Joel',
'venue' => 'Madison Square Garden',
'genres' => [ 'rock', 'soft rock', 'pop rock' ],
'ticketsSold' => 12852,
'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')),
],
];
Concert::insert($data);

在本节中,您可以学习如何在您的Laravel应用程序中修改MongoDB集合中的文档。使用更新操作来修改现有文档或插入一个匹配搜索条件的文档。

您可以在Eloquent模型的实例上持久化更改,或使用Eloquent的流畅语法在返回Laravel集合对象的函数上链式调用更新操作。

本节提供了以下更新操作的示例

您可以通过以下方式更新文档

  • 修改模型的实例,并通过调用save()方法保存更改。

  • 链式调用方法以检索模型的实例并在其上执行更新,通过调用update()方法。

以下示例展示了如何通过修改模型的实例并调用其save()方法来更新文档

通过在实例上调用save()方法来更新文档
$concert = Concert::first();
$concert->venue = 'Manchester Arena';
$concert->ticketsSold = 9543;
$concert->save();

save()方法成功执行时,调用该方法的模型实例包含更新后的值。

如果操作失败,Laravel集成将模型实例分配一个null值。

以下示例展示了如何通过链式调用方法来检索和更新第一个匹配的文档以更新文档

通过链式调用update()方法来更新匹配的文档。
$concert = Concert::where(['performer' => 'Brad Mehldau'])
->orderBy('id')
->first()
->update(['venue' => 'Manchester Arena', 'ticketsSold' => 9543]);

注意

orderBy()调用根据_id字段对结果进行排序,以保证一致的排序顺序。有关MongoDB中排序的更多信息,请参阅服务器手册中的自然排序词汇表条目。

update()方法成功执行时,操作返回更新文档的数量。

如果调用中的检索部分没有匹配任何文档,Laravel集成返回以下错误

Error: Call to a member function update() on null

要更新一个或多个文档,将update()方法链接到检索文档的方法的结果,例如where()方法的结果。

以下示例展示了如何链式调用检索匹配的文档并更新它们

Concert::whereIn('venue', ['Philharmonie de Paris', 'Soldier Field'])
->update(['venue' => 'Concertgebouw', 'ticketsSold' => 0]);

update()方法成功执行时,操作返回更新文档的数量。

如果调用中的检索部分没有匹配集合中的任何文档,Laravel集成返回以下错误

Error: Call to a member function update() on null

一个upsert操作允许您在单个操作中执行更新或插入。此操作简化了更新文档或在没有找到时插入文档的任务。

从v4.7版本开始,您可以通过以下任何一种方法执行upsert操作:

  • upsert():当您使用此方法时,可以执行批量upsert,在一次操作中更改或插入多个文档。

  • update():当您使用此方法时,必须指定upsert选项以更新所有匹配查询筛选器的文档,或者在没有匹配文档的情况下插入一个文档。只有此upsert方法在v4.6及更早版本中受支持。

upsert(array $values, array|string $uniqueBy, array|null $update)方法接受以下参数

  • $values:要更新或插入的文档的字段和值的数组。

  • $uniqueBy:第一个数组参数中唯一标识文档的字段列表。

  • $update:可选的更新字段列表,如果存在匹配的文档。如果省略此参数,Laravel集成更新所有字段。

要指定upsert()方法中的upsert,设置参数如下所示

YourModel::upsert(
[/* documents to update or insert */],
'/* unique field */',
[/* fields to update */],
);

此示例演示了如何使用upsert()方法在一次操作中执行更新或插入。点击查看输出按钮以查看当集合中已存在一个文档,其中performer的值为'Angel Olsen'时,结果数据的变化

Concert::upsert([
['performer' => 'Angel Olsen', 'venue' => 'Academy of Music', 'ticketsSold' => 275],
['performer' => 'Darondo', 'venue' => 'Cafe du Nord', 'ticketsSold' => 300],
], 'performer', ['ticketsSold']);
{
"_id": "...",
"performer": "Angel Olsen",
"venue": "State Theatre",
"genres": [
"indie",
"rock"
],
"ticketsSold": 275,
"updated_at": ...
},
{
"_id": "...",
"performer": "Darondo",
"venue": "Cafe du Nord",
"ticketsSold": 300,
"updated_at": ...
}

在文档中,当performer字段的值为'Angel Olsen'时,venue字段的值没有被更新,因为upsert操作指定只更新ticketsSold字段。

要在update()方法中指定upsert,将upsert选项设置为true,如下代码示例所示

YourModel::where(/* match criteria */)
->update(
[/* update data */],
['upsert' => true]);

update()方法与查询链式使用时,它执行以下操作之一

  • 如果查询匹配文档,则update()方法修改匹配的文档。

  • 如果查询匹配零个文档,则update()方法插入一个包含更新数据和相等匹配条件数据的文档。

此示例演示了如何将upsert选项传递给update()方法以执行单个操作中的更新或插入。单击查看输出按钮以查看在没有匹配文档时插入的示例文档

Concert::where(['performer' => 'Jon Batiste', 'venue' => 'Radio City Music Hall'])
->update(
['genres' => ['R&B', 'soul'], 'ticketsSold' => 4000],
['upsert' => true],
);
{
"_id": "660c...",
"performer": "Jon Batiste",
"venue": "Radio City Music Hall",
"genres": [
"R&B",
"soul"
],
"ticketsSold": 4000,
"updated_at": ...
}

在本节中,您可以看到以下操作示例,这些操作用于更新MongoDB文档中的数组值

以下示例通过以下插入操作修改了创建的示例文档

Concert::create([
'performer' => 'Mitsuko Uchida',
'genres' => ['classical', 'dance-pop'],
]);

本节展示了如何使用 push() 方法向 MongoDB 文档中的数组添加值。您可以传递一个或多个要添加的值,并将可选参数 unique 设置为 true 以跳过添加数组中的任何重复值。以下代码示例展示了 push() 方法调用的结构

YourModel::where(<match criteria>)
->push(
<field name>,
[<values>], // array or single value to add
unique: true); // whether to skip existing values

以下示例展示了如何将值 "baroque" 添加到匹配文档的 genres 数组字段。点击 查看输出 按钮,查看更新后的文档

Concert::where('performer', 'Mitsuko Uchida')
->push(
'genres',
['baroque'],
);
{
"_id": "660eb...",
"performer": "Mitsuko Uchida",
"genres": [
"classical",
"dance-pop",
],
"updated_at": ...,
"created_at": ...
}

本节展示了如何使用 pull() 方法从 MongoDB 文档中的数组中删除值。您可以传递一个或多个要从数组中删除的值。以下代码示例展示了 pull() 方法调用的结构

YourModel::where(<match criteria>)
->pull(
<field name>,
[<values>]); // array or single value to remove

以下示例展示了如何从 genres 数组字段中删除数组值 "classical""dance-pop"。点击 查看输出 按钮,查看更新后的文档

Concert::where('performer', 'Mitsuko Uchida')
->pull(
'genres',
['dance-pop', 'classical'],
);
{
"_id": "660e...",
"performer": "Mitsuko Uchida",
"genres": [],
"updated_at": ...,
"created_at": ...
}

本节展示了如何使用$位置操作符来更新MongoDB文档中的特定数组元素。$操作符表示第一个与查询匹配的数组元素。以下代码示例展示了在单个匹配文档上对位置操作符更新调用的结构

注意

目前,Laravel集成仅在此DB外观上提供此操作,而不是在Eloquent ORM上。

DB::connection('mongodb')
->getCollection(<collection name>)
->updateOne(
<match criteria>,
['$set' => ['<array field>.$' => <replacement value>]]);

以下示例展示了如何将"dance-pop"数组值替换为"contemporary"。点击查看输出按钮以查看更新后的文档

$match = ['performer' => 'Mitsuko Uchida', 'genres' => 'dance-pop'];
$update = ['$set' => ['genres.$' => 'contemporary']];
DB::connection('mongodb')
->getCollection('concerts')
->updateOne($match, $update);
{
"_id": "660e...",
"performer": "Mitsuko Uchida",
"genres": [
"classical",
"contemporary"
],
"updated_at": ...,
"created_at": ...
}

要了解更多有关数组更新操作符的信息,请参阅服务器手册中的数组更新操作符

在本节中,您可以了解如何使用Laravel集成从MongoDB集合中删除文档。使用删除操作从MongoDB数据库中删除数据。

本节提供了以下删除操作的示例

要了解Laravel集成中可用的Laravel功能,这些功能可以修改删除行为,请参阅以下部分

  • 软删除,允许您将文档标记为已删除,而不是从数据库中删除它们

  • 修剪,允许您定义使文档有资格自动删除的条件

您可以通过以下方式删除一个文档

  • 在模型的实例上调用 $model->delete() 方法。

  • 在模型上调用 Model::destroy($id) 方法,传递要删除的文档的 id。

  • 通过调用 delete() 方法来链式调用方法,以检索和删除模型的实例。

以下示例展示了如何通过在模型的实例上调用 $model->delete() 来删除文档

通过在实例上调用 delete() 方法来删除文档。
$concert = Concert::first();
$concert->delete();

delete() 方法成功时,操作返回被删除的文档数量。

如果调用的检索部分不匹配集合中的任何文档,则操作返回 0

以下示例展示了如何通过将文档的 id 值传递给 Model::destroy($id) 方法来删除文档

通过其 id 值来删除文档。
$id = 'MSG-0212252000';
Concert::destroy($id);

destroy() 方法成功时,它返回被删除的文档数量。

如果 id 值不匹配任何文档,则 destroy() 方法返回 0

以下示例展示了如何链式调用以检索第一个匹配的文档并删除它

通过链式调用 delete() 方法来删除匹配的文档。
Concert::where('venue', 'Carnegie Hall')
->limit(1)
->delete();

注意

orderBy()调用根据_id字段对结果进行排序,以保证一致的排序顺序。有关MongoDB中排序的更多信息,请参阅服务器手册中的自然排序词汇表条目。

delete() 方法成功时,它返回被删除的文档数量。

如果 where() 方法不匹配任何文档,则 delete() 方法返回 0

您可以通过以下方式删除多个文档

  • 调用 Model::destroy($ids) 方法,传入要删除的文档或模型实例的ID列表。

  • 通过链式调用方法获取多个对象的Laravel集合对象,并通过调用 delete() 方法来删除它们。

以下示例展示了如何通过将表示ID值的数组$ids传递给 destroy() 方法来删除文档

通过ID删除文档。
$ids = [3, 5, 7, 9];
Concert::destroy($ids);

提示

当传入大量列表时,destroy() 方法的性能会受到影响。为了更好的性能,请使用 Model::whereIn('id', $ids)->delete() 代替。

destroy() 方法成功时,它返回被删除的文档数量。

如果ID值不匹配任何文档,则 destroy() 方法返回 0

以下示例展示了如何通过链式调用获取匹配的文档并删除它们

通过链式调用获取匹配的文档并删除它们。
Concert::where('ticketsSold', '>', 7500)
->delete();

delete() 方法成功时,它返回被删除的文档数量。

如果 where() 方法不匹配任何文档,则 delete() 方法返回 0

返回

读取操作