Overview
在本指南中,您可以学习;了解如何使用 Laravel查询构建器的 Laravel 集成扩展来处理MongoDB 数据库。 查询构建器允许您使用单一语法和流畅的界面为任何支持的数据库写入查询。
注意
Laravel 集成扩展了 Laravel 的查询构建器和 Eloquent ORM,它们可以运行类似的数据库操作。 要学习;了解有关使用 Eloquent 模型检索文档的更多信息,请参阅读取操作。
Laravel 提供了一个门面来访问查询构建器类DB ,它允许您执行数据库操作。 外观是类的静态接口,它使语法更加简洁,避免运行时错误并提高可测试性。
Laravel 集成提供了DB方法table()来访问权限集合。 用于指定命令和任何约束的链式方法。 然后,在末尾链接get()方法以运行这些方法并检索结果。 以下示例显示了查询构建器调用的事务语法:
DB::table('<collection name>') // chain methods by using the "->" object operator ->get();
提示
在使用DB::table()方法之前,请确保将 MongoDB 指定为应用程序的默认数据库连接。 有关设置数据库连接的说明,请参阅快速入门中的配置 MongoDB 连接步骤。
如果 MongoDB 不是应用程序的默认数据库,则可以使用DB::connection()方法指定 MongoDB 连接。 将连接名称传递给connection()方法,如以下代码所示:
$connection = DB::connection('mongodb');
本指南提供了以下类型的查询构建器操作的示例:
开始之前
要运行本指南中的代码示例,请完成快速入门教程以配置 Web 应用程序,将示例数据集加载到 MongoDB 部署中,并从控制器方法运行示例代码。 要查看 JSON 文档形式的预期代码输出,请使用快速入门的可选查看 JSON 文档形式的结果步骤中显示的toJson()方法。
要使用查询构建器执行读取和写入操作,请导入Illuminate\Support\Facades\DB门面并编写查询。
检索匹配文档
本部分包括以下操作符类别中读取操作的查询构建器示例:
where 方法示例
以下示例演示如何使用where()查询构建器方法从movies集合中检索包含imdb.rating字段值恰好为9.3的文档。 单击VIEW OUTPUT按钮查看查询返回的结果:
$result = DB::connection('mongodb') ->table('movies') ->where('imdb.rating', 9.3) ->get();
逻辑条件操作
本节中的示例显示可用于执行以下逻辑条件操作的查询构建器语法:
逻辑 OR 示例
以下示例展示了如何链接orWhere()查询构建器方法以从movies集合中检索与1955的year值匹配或与title值"Back to the Future"匹配的文档:
$result = DB::connection('mongodb') ->table('movies') ->where('year', 1955) ->orWhere('title', 'Back to the Future') ->get();
逻辑与示例
以下示例展示了如何链式使用where() 查询构建器方法,从movies imdb.rating集合中检索同时匹配大于8.5 的 值和小于year 的1940 值的文档:
$result = DB::connection('mongodb') ->table('movies') ->where('imdb.rating', '>', 8.5) ->where('year', '<', 1940) ->get();
逻辑 NOT 示例
以下示例演示如何调用whereNot()查询构建器方法从movies集合中检索与imdb.rating值不大于2的文档匹配的文档。 这相当于匹配所有imdb.rating小于或等于2的文档:
$result = DB::connection('mongodb') ->table('movies') ->whereNot('imdb.rating', '>', 2) ->get();
嵌套逻辑操作符组示例
以下示例展示了如何链接where()查询构建器方法以从movies集合中检索符合以下两个条件的文档。 此示例将闭包作为where()查询构建器方法的第一个参数传递,以对逻辑 OR 组进行分组:
imdb.rating值大于8.5year值为1986或1996
$result = DB::connection('mongodb') ->table('movies') ->where('imdb.rating', '>', 8.5) ->where(function (Builder $query) { return $query ->where('year', 1986) ->orWhere('year', 1996); })->get();
范围和类型检查
本部分中的示例展示了可用于通过以下范围查询和类型检查操作来匹配值的查询构建器语法:
数值范围示例
以下示例演示如何使用whereBetween()查询构建器方法从movies集合中检索包含介于9和9.5之间的imdb.rating值的文档:
$result = DB::connection('mongodb') ->table('movies') ->whereBetween('imdb.rating', [9, 9.5]) ->get();
Null 或缺失值示例
以下示例演示如何使用whereNull()查询构建器方法从movies集合中检索省略了runtime值或字段的文档:
$result = DB::connection('mongodb') ->table('movies') ->whereNull('runtime') ->get();
设置示例的一个或多个值
以下示例演示如何使用whereIn()查询构建器方法从movies集合中检索与指定集合中的至少一个title值匹配的文档:
$result = DB::table('movies') ->whereIn('title', ['Toy Story', 'Shrek 2', 'Johnny English']) ->get();
匹配日期示例
以下示例演示如何使用whereDate()查询构建器方法从movies集合中检索与released字段中2010-1-15指定日期匹配的文档:
$result = DB::connection('mongodb') ->table('movies') ->whereDate('released', '2010-1-15') ->get();
文本模式匹配示例
以下示例演示如何结合使用like查询运算符和where()查询构建器方法,通过指定的文本模式从movies集合中检索文档。
文本模式可以包含混合有以下通配符的文本:
%匹配零个或多个字符_匹配单个字符
$result = DB::table('movies') ->where('title', 'like', '%spider_man%') ->get();
whereLike() 和 whereNotLike() 方法
以下方法提供与使用like查询运算符匹配模式相同的功能:
whereLike():匹配指定的模式。 默认,此方法执行不区分大小写的匹配。 您可以通过将true作为最后一个参数传递给该方法来启用区分大小写。whereNotLike():匹配字段值不包含指定string模式的文档。
以下示例演示如何使用whereLike()方法匹配文档,其中title字段的值与模式'Start%'匹配并启用区分大小写:
$result = DB::connection('mongodb') ->table('movies') ->whereLike('title', 'Start%', true) ->get();
Retrieve Distinct Values
以下示例演示如何使用distinct()查询构建器方法检索movies集合中文档的year字段的所有不同值。
$result = DB::table('movies') ->distinct('year')->get();
聚合(Aggregation)
本节中的示例展示了可用于执行聚合的查询构建器语法。 聚合是根据一组查询结果数据计算值的操作。 您可以使用聚合来计算并返回以下信息:
按通用字段值分组的结果示例
以下示例演示如何使用groupBy()查询构建器方法检索按runtime字段的共享值分组的文档数据。 此示例链接了以下操作,以匹配movies集合中的文档,这些文档包含G的rated值,并为每个不同的runtime值包含一部电影的title字段:
使用
where()方法,仅匹配rated字段值为"G"的文档使用
groupBy()方法,按分配了_id字段的runtime字段的不同值对数据进行分组使用
orderBy()方法按runtime字段对群组进行排序通过在
get()方法中指定,返回分组结果中最后一个文档的title数据
提示
groupBy()方法调用 MongoDB $group聚合操作符和$last累加器操作符。 要了解有关这些操作符的更多信息,请参阅 MongoDB Server手册中的 $group(聚合) 。
$result = DB::table('movies') ->where('rated', 'G') ->groupBy('runtime') ->orderBy('runtime', 'asc') ->get(['title']);
结果数量示例
以下示例演示如何使用count()查询构建器方法返回movies集合中包含的文档数:
$result = DB::table('movies') ->count();
字段最大值示例
以下示例演示如何使用max()查询构建器方法返回整个movies集合中runtime字段的最大数值:
$result = DB::table('movies') ->max('runtime');
字段最小值示例
以下示例演示如何使用min()查询构建器方法返回整个movies集合中year字段的最小数值:
$result = DB::table('movies') ->min('year');
字段平均值示例
以下示例演示如何使用avg()查询构建器方法返回整个movies集合中imdb.rating值的数值平均值或算术平均值。
$result = DB::table('movies') ->avg('imdb.rating');
字段求和值示例
以下示例演示如何使用sum()查询构建器方法返回整个movies集合中imdb.votes值的数值总计:
$result = DB::table('movies') ->sum('imdb.votes');
聚合匹配结果示例
以下示例展示了如何从与查询匹配的结果中聚合数据。 该查询匹配2000年之后的所有电影,并使用avg()方法计算这些匹配项的imdb.rating平均值:
$result = DB::table('movies') ->where('year', '>', 2000) ->avg('imdb.rating');
设置查询级选项
您可以通过在查询构建器上设置选项来修改 Laravel 集成执行操作的方式。 您可以将选项大量传递给 options()查询构建器方法,以指定查询选项。
以下代码演示了如何将注释附加到查询:
$result = DB::connection('mongodb') ->table('movies') ->where('year', 2000) ->options(['comment' => 'hello']) ->get();
The query builder accepts the same options that you can set for the find() method in the MongoDB PHP Library. Some of the options to modify query results, such as skip, sort, and limit, are settable directly as query builder methods and are described in the Modify Query Results section of this guide. We recommend that you use these methods instead of passing them as options.
修改查询结果
本部分包括以下函数的查询构建器示例,这些函数修改查询结果的顺序和格式:
排序结果示例
以下示例演示如何使用orderBy()查询构建器方法,以降序排列与title字段中按imdb.rating值指定的筛选器匹配的结果:
$result = DB::table('movies') ->where('title', 'like', 'back to the future%') ->orderBy('imdb.rating', 'desc') ->get();
省略指定数量的结果示例
以下示例演示如何使用skip()查询构建器方法省略与title字段中指定的筛选器匹配的前四个结果,并按year值升序排序:
$result = DB::table('movies') ->where('title', 'like', 'star trek%') ->orderBy('year', 'asc') ->skip(4) ->get();
在结果示例中显示字段和数组值的子集
以下示例演示如何使用project()查询构建器方法匹配imdb.rating值大于8.5的文档,并仅返回以下字段值:
电影标题
titlecast数组字段的第二个到第四个值(如果存在)文档
_id字段,该字段会自动包含在
$result = DB::table('movies') ->where('imdb.rating', '>', 8.5) ->project([ 'title' => 1, 'cast' => ['$slice' => [1, 3]], ]) ->get();
对结果进行分页示例
以下示例展示了如何使用paginate()查询构建器方法将整个movie集合划分为15文档的离散结果集。 该示例还包括一个排序顺序,用于按imdb.votes字段以降序排列结果,以及一个仅包括结果中的特定字段的投影。
$resultsPerPage = 15; $projectionFields = ['title', 'runtime', 'imdb.rating']; $result = DB::table('movies') ->orderBy('imdb.votes', 'desc') ->paginate($resultsPerPage, $projectionFields);
要学习;了解有关分页的更多信息,请参阅 Laravel 文档中的对查询生成器结果进行分页。
使用 MongoDB 操作检索数据
本节包括查询构建器示例,展示如何使用以下 MongoDB 特定的查询操作:
包含字段示例
以下示例展示了如何使用exists()查询构建器方法来匹配包含字段random_review的文档:
$result = DB::table('movies') ->exists('random_review', true);
包含所有字段示例
以下示例演示如何使用all查询运算符和where()查询构建器方法来匹配包含所有指定字段的文档:
$result = DB::table('movies') ->where('movies', 'all', ['title', 'rated', 'imdb.rating']) ->get();
匹配数组大小示例
以下示例演示如何使用where()查询构建器方法传递size查询运算符,以匹配包含directors字段的文档,而该字段包含恰好包含五个元素的数组:
$result = DB::table('movies') ->where('directors', 'size', 5) ->get();
To learn more about this query operator, see $size in the Server manual.
匹配数据类型示例
以下示例演示如何使用where()查询构建器方法传递type查询运算符,以匹配released字段中包含4类型值(对应于数组数据类型)的文档。
$result = DB::table('movies') ->where('released', 'type', 4) ->get();
匹配使用模计算的值示例
以下示例展示了如何通过where()查询构建器方法传递mod查询运算符,以使用表达式year % 2 == 0来匹配文档,从而匹配year字段的偶数值:
$result = DB::table('movies') ->where('year', 'mod', [2, 0]) ->get();
匹配正则表达式
以下示例演示如何使用where()查询构建器方法传递REGEX查询运算符,以匹配包含与指定正则表达式匹配的title字段的文档:
$result = DB::connection('mongodb') ->table('movies') ->where('title', 'REGEX', new Regex('^the lord of .*', 'i')) ->get();
To learn more about regular expression queries in MongoDB, see $regex in the Server manual.
运行 MongoDB 查询 API 操作示例
以下示例展示了如何使用whereRaw()查询构建器方法来运行使用 MongoDB 查询 API 语法编写的查询操作:
$result = DB::table('movies') ->whereRaw([ 'imdb.votes' => ['$gte' => 1000 ], '$or' => [ ['imdb.rating' => ['$gt' => 7]], ['directors' => ['$in' => [ 'Yasujiro Ozu', 'Sofia Coppola', 'Federico Fellini' ]]], ], ])->get();
以下代码显示了等效的 MongoDB 查询 API 语法:
db.movies.find({ "imdb.votes": { $gte: 1000 }, $or: [{ imdb.rating: { $gt: 7 }, directors: { $in: [ "Yasujiro Ozu", "Sofia Coppola", "Federico Fellini" ] } }]});
To learn more about the MongoDB Query API, see MongoDB Query API in the Server manual.
匹配数组元素示例
以下示例演示如何使用where()查询构建器方法传递elemMatch查询运算符,以匹配包含数组元素的文档,而该数组元素与指定查询中的至少一个条件匹配:
$result = DB::table('movies') ->where('writers', 'elemMatch', ['$in' => ['Maya Forbes', 'Eric Roth']]) ->get();
To learn more about regular expression queries in MongoDB, see the $elemMatch operator in the Server manual.
指定游标超时示例
以下示例演示如何使用timeout()方法指定等待游标操作完成的最长持续时间。
$result = DB::table('movies') ->timeout(2) // value in seconds ->where('year', 2001) ->get();
注意
此设置指定以秒而不是毫秒为单位的maxTimeMS值。 要了解有关maxTimeMS值的更多信息,请参阅 PHP 库文档中的MongoDBCollection::find() 。
使用地理空间操作匹配位置
本部分中的示例展示了可用于对 GeoJSON 或坐标对数据执行地理空间查询以检索以下类型的位置的查询构建器语法:
重要
要在 MongoDB 中执行 GeoJSON 查询,必须在集合上创建2d或2dsphere索引。 要了解如何创建地理空间索引,请参阅模式生成器指南中的创建地理空间索引部分。
To learn more about GeoJSON objects that MongoDB supports, see GeoJSON Objects in the Server manual.
邻近位置示例
以下示例展示了如何使用near查询运算符和where()查询构建器方法来匹配包含与 GeoJSON Point 对象相距不超过50米的位置的文档:
$results = DB::table('theaters') ->where('location.geo', 'near', [ '$geometry' => [ 'type' => 'Point', 'coordinates' => [ -86.6423, 33.6054, ], ], '$maxDistance' => 50, ])->get();
在区域内示例
以下示例演示如何使用geoWithin查询运算符和where()查询构建器方法来匹配包含指定Polygon GeoJSON 对象边界内的位置的文档:
$results = DB::table('theaters') ->where('location.geo', 'geoWithin', [ '$geometry' => [ 'type' => 'Polygon', 'coordinates' => [ [ [-72, 40], [-74, 41], [-72, 39], [-72, 40], ], ], ], ])->get();
相交几何图形示例
以下示例演示如何使用geoInstersects查询运算符和where()查询构建器方法来匹配包含与指定LineString GeoJSON 对象相交的位置的文档:
$results = DB::table('theaters') ->where('location.geo', 'geoIntersects', [ '$geometry' => [ 'type' => 'LineString', 'coordinates' => [ [-73.600525, 40.74416], [-72.600525, 40.74416], ], ], ])->get();
附近匹配的邻近数据示例
以下示例展示如何使用geoNear聚合操作符和raw()查询构建器方法来执行返回元数据(例如每个匹配项的邻近信息)的聚合:
$results = DB::table('theaters')->raw( function (Collection $collection) { return $collection->aggregate([ [ '$geoNear' => [ 'near' => [ 'type' => 'Point', 'coordinates' => [-118.34, 34.10], ], 'distanceField' => 'dist.calculated', 'maxDistance' => 500, 'includeLocs' => 'dist.location', 'spherical' => true, ], ], ]); }, )->toArray();
To learn more about this aggregation operator, see $geoNear operator in the Server manual.
使用 MongoDB 写操作写入数据
本节包括查询构建器示例,展示如何使用以下特定于 MongoDB 的写入操作:
更新或插入文档示例
从 v 4.7开始, 您可以使用以下任一查询生成器方法执行更新或更新或插入(upsert)操作:
upsert():使用此方法时,您可以执行批处理更新或插入(upsert)或插入,以便在一次操作中更改或插入多个文档。update():使用此方法时,必须指定upsert选项以更新与查询过滤匹配的所有文档,如果没有文档匹配,则插入一个文档。 版本 v 4.6及更早版本仅支持此更新或更新或插入(upsert)方法。
更新或插入方法
upsert(array $values, array|string $uniqueBy, array|null $update)查询构建器方法接受以下参数:
$values:指定要更新或插入的文档的字段和值的数组。$uniqueBy:唯一标识第一个大量参数中的文档的字段列表。$update:存在匹配文档时要更新的可选字段列表。 如果省略此参数,Laravel 集成将更新所有字段。
以下示例展示了如何使用upsert()查询构建器方法根据以下说明更新或插入文档:
指定一个文档,其中
title字段的值为'Inspector Maigret'、recommended字段的值为false以及runtime字段的值为128。指定一个文档,其中
title字段的值为'Petit Maman'、recommended字段的值为true以及runtime字段的值为72。指示
title字段唯一标识操作范围内的文档。仅更新匹配文档中的
recommended字段。
$result = DB::table('movies') ->upsert( [ ['title' => 'Inspector Maigret', 'recommended' => false, 'runtime' => 128], ['title' => 'Petit Maman', 'recommended' => true, 'runtime' => 72], ], 'title', 'recommended', );
upsert()查询构建器方法会返回该操作更新、插入和修改的文档数。
注意
upsert() 方法不trigger事件。 要通过更新或更新或插入(upsert)操作trigger事件,可以改用 createOrFirst() 方法。
更新方法
以下示例演示如何使用update()查询构建器方法和upsert选项更新匹配的文档,或插入包含指定数据的文档(如果不存在)。 当您将upsert选项设置为true且文档不存在时,该命令会同时插入数据以及where()查询操作中指定的title字段和值:
$result = DB::table('movies') ->where('title', 'Will Hunting') ->update( [ 'plot' => 'An autobiographical movie', 'year' => 1998, 'writers' => [ 'Will Hunting' ], ], ['upsert' => true], );
update()查询构建器方法会返回该操作更新或插入的文档数。
递增数值示例
以下示例演示如何使用increment()查询构建器方法将3000添加到匹配文档中的imdb.votes字段的值:
$result = DB::table('movies') ->where('title', 'Field of Dreams') ->increment('imdb.votes', 3000);
increment()查询构建器方法会返回该操作更新的文档数。
从 Laravel Integration v 4.8开始, 您还可以使用incrementEach()查询构建器方法在单个操作中递增多个值。 以下示例使用incrementEach()方法增加匹配文档中awards.wins和imdb.votes字段的值:
$result = DB::table('movies') ->where('title', 'Lost in Translation') ->incrementEach([ 'awards.wins' => 2, 'imdb.votes' => 1050, ]);
注意
如果向increment()或incrementEach()方法传递一个没有值或不存在于匹配文档中的字段,这些方法会将指定字段初始化为递增值。
递减数值示例
以下示例演示如何使用decrement()查询构建器方法从匹配文档的imdb.rating字段的值中减去0.2 :
$result = DB::table('movies') ->where('title', 'Sharknado') ->decrement('imdb.rating', 0.2);
decrement()查询构建器方法会返回该操作更新的文档数。
从 Laravel Integration v 4.8开始, 您还可以使用decrementEach()查询构建器方法在单个操作中递减多个值。 以下示例使用decrementEach()方法减少匹配文档中metacritic和imdb.rating字段的值:
$result = DB::table('movies') ->where('title', 'Dunkirk') ->decrementEach([ 'metacritic' => 1, 'imdb.rating' => 0.4, ]);
注意
如果向decrement()或decrementEach()方法传递没有值或不存在于匹配文档中的字段,这些方法会将指定字段初始化为递减值。
添加数组元素示例
以下示例展示了如何使用push()查询构建器方法将"Gary Cole"添加到匹配文档的cast数组字段:
$result = DB::table('movies') ->where('title', 'Office Space') ->push('cast', 'Gary Cole');
push()查询构建器方法会返回该操作更新的文档数。
删除数组元素示例
以下示例演示如何使用pull()查询构建器方法从查询匹配的文档中的genres字段中删除"Adventure"值:
$result = DB::table('movies') ->where('title', 'Iron Man') ->pull('genres', 'Adventure');
pull()查询构建器方法会返回该操作更新的文档数。
删除字段示例
以下示例演示如何使用unset()查询构建器方法从查询匹配的文档中删除tomatoes.viewer字段和值:
$result = DB::table('movies') ->where('title', 'Final Accord') ->unset('tomatoes.viewer');
unset()查询构建器方法会返回该操作更新的文档数。