写入操作
本页内容
概述
在本指南中,您可以学习如何使用Laravel MongoDB在MongoDB集合上执行写入操作。写入操作包括根据指定条件插入、更新和删除数据。
本指南展示了以下任务的执行方法
示例模型
本指南中的写入操作引用以下Eloquent模型类
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']; }
插入文档
在本节中,您可以了解如何使用Laravel MongoDB将文档插入MongoDB集合。
在插入文档时,请确保数据不违反集合上的任何唯一索引。在插入集合的第一个文档或创建新集合时,MongoDB会自动在 _id
字段上创建唯一索引。
有关使用Laravel架构构建器在MongoDB集合上创建索引的更多信息,请参阅Schema Builder文档中的 管理索引 部分。
有关Laravel集成中Eloquent模型的相关信息,请参阅 Eloquent模型 部分。
插入文档示例
以下示例展示了如何使用 save()
Eloquent 方法将 Concert
模型实例作为MongoDB文档插入。
当 save()
方法成功执行时,您可以通过调用该方法的模型实例来访问它。
如果操作失败,模型实例将被分配为null
。
以下示例代码执行以下操作
创建
Concert
模型的新实例将字符串值分配给
performer
和venue
字段将字符串数组分配给
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()
方法来更新文档
$concert = Concert::first(); $concert->venue = 'Manchester Arena'; $concert->ticketsSold = 9543; $concert->save();
当save()
方法成功执行时,调用该方法的模型实例包含更新后的值。
如果操作失败,Laravel集成将模型实例分配一个null
值。
以下示例展示了如何通过链式调用方法来检索和更新第一个匹配的文档以更新文档
$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方法
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()
来删除文档
$concert = Concert::first(); $concert->delete();
当 delete()
方法成功时,操作返回被删除的文档数量。
如果调用的检索部分不匹配集合中的任何文档,则操作返回 0
。
以下示例展示了如何通过将文档的 id 值传递给 Model::destroy($id)
方法来删除文档
$id = 'MSG-0212252000'; Concert::destroy($id);
当 destroy()
方法成功时,它返回被删除的文档数量。
如果 id 值不匹配任何文档,则 destroy()
方法返回 0
。
以下示例展示了如何链式调用以检索第一个匹配的文档并删除它
Concert::where('venue', 'Carnegie Hall') ->limit(1) ->delete();
注意
orderBy()
调用根据_id
字段对结果进行排序,以保证一致的排序顺序。有关MongoDB中排序的更多信息,请参阅服务器手册中的自然排序词汇表条目。
当 delete()
方法成功时,它返回被删除的文档数量。
如果 where()
方法不匹配任何文档,则 delete()
方法返回 0
。
删除多个文档示例
您可以通过以下方式删除多个文档
调用
Model::destroy($ids)
方法,传入要删除的文档或模型实例的ID列表。通过链式调用方法获取多个对象的Laravel集合对象,并通过调用
delete()
方法来删除它们。
以下示例展示了如何通过将表示ID值的数组$ids
传递给 destroy()
方法来删除文档
$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
。