MongoDB 條件操作符
Exists(判斷字段是否存在)
查詢(xún)所有存在age字段的記錄
User::where('age', 'exists', true)->get();
查詢(xún)所有不存在name字段的記錄
User::where('age', 'exists', false)->get();
All(匹配所有)
這個(gè)操作符跟SQL語(yǔ)法的in類(lèi)似,但不同的是, in只需滿(mǎn)足( )內(nèi)的某一個(gè)值即可,而$all必須滿(mǎn)足[ ]內(nèi)的所有值
User::where('roles', 'all', ['moderator', 'author'])->get();
Size(數(shù)組元素個(gè)數(shù))
對(duì)于查詢(xún)數(shù)組來(lái)說(shuō)是非常有用的,顧名思義,可以用它查詢(xún)特定長(zhǎng)度的數(shù)組。
User::where('tags', 'size', 3)->get();
Regex(正則表達(dá)式匹配)
選擇值與指定正則表達(dá)式匹配的文檔。
User::where('name', 'regex', new \MongoDB\BSON\Regex("/.*doe/i"))->get();
注意:您也可以使用Laravel正則表達(dá)式操作。 這些更靈活,會(huì)自動(dòng)將正則表達(dá)式字符串轉(zhuǎn)換為MongoDB \ BSON \ Regex對(duì)象。
User::where('name', 'regexp', '/.*doe/i'))->get();
反之:
User::where('name', 'not regexp', '/.*doe/i'))->get();
Type(類(lèi)型)
User::where('age', 'type', 2)->get();
Mod(取模運(yùn)算)
查詢(xún)age取模10等于0的數(shù)據(jù)
User::where('age', 'mod', [10, 0])->get();
Near(指定地理空間查詢(xún)從最近到最遠(yuǎn)返回文檔的點(diǎn)。)
$ near運(yùn)算符可以指定GeoJSON點(diǎn)或傳統(tǒng)坐標(biāo)點(diǎn)。
$users = User::where('location', 'near', [
????????'$geometry' => [
????????'type' => 'Point',
????????'coordinates' => [
????????????????-0.1367563,
????????????????51.5100913,
????????????],
????????],
????????'$maxDistance' => 50,
]);
GeoWithin(選擇具有完全在指定形狀內(nèi)的地理空間數(shù)據(jù)的文檔。)
$users = User::where('location', 'geoWithin', [
'$geometry' => [
????????'type' => 'Polygon',
????????'coordinates' => [[
????????????[-0.1450383,51.5069158,],
????????????[-0.1367563,51.5100913,],
????????????[-0.1270247,51.5013233,],
????????????[-0.1450383,51.5069158,],
????????]],
????],
????]);
GeoIntersects(選擇地理空間數(shù)據(jù)與指定GeoJSON對(duì)象相交的文檔;即數(shù)據(jù)和指定對(duì)象的交集是非空的。)
$locations = Location::where('location', 'geoIntersects', [
'$geometry' => [
????????'type' => 'LineString',
????????'coordinates' => [
????????????[-0.144044,51.515215,],[-0.129545,51.507864,],
????????],
????????],
????]);
Where
匹配滿(mǎn)足JavaScript表達(dá)式的文檔。 有關(guān)更多信息,請(qǐng)查看 http://docs.mongodb.org/manual/reference/operator/query/where/#op._S_where
Inserts, updates and deletes
插入,更新和刪除記錄就像原始的Eloquent一樣。
通過(guò)模型插入數(shù)據(jù)
$user = new User;
$user->name = 'John';
$user->save();
您還可以使用create方法將新模型保存在一行中:
User::create(['name' => 'John']);
通過(guò)模型更新數(shù)據(jù)
要更新模型,您可以檢索它,更改屬性并使用save方法。
$user = User::first();
$user->email = 'john@foo.com';
$user->save();
通過(guò)模型刪除數(shù)據(jù)
要?jiǎng)h除模型,只需在實(shí)例上調(diào)用delete方法:
$user = User::first();
$user->delete();
或者通過(guò)主鍵刪除
User::destroy('517c43667db388101e00000f');
Dates
Eloquent允許您使用Carbon / DateTime對(duì)象而不是MongoDate對(duì)象。 在內(nèi)部,這些日期在保存到數(shù)據(jù)庫(kù)時(shí)將轉(zhuǎn)換為MongoDate對(duì)象。 如果您希望在非默認(rèn)日期字段中使用此功能,則需要按照此處所述手動(dòng)指定它們:http://laravel.com/docs/eloquent#date-mutators
示例:
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class User extends Eloquent {
protected $dates = ['birthday'];
}
Which allows you to execute queries like:
$users = User::where('birthday', '>', new DateTime('-18 years'))->get();
MongoDB 關(guān)系
MongoDB的關(guān)系表示多個(gè)文檔之間在邏輯上的相互聯(lián)系文檔間可以通過(guò)嵌入和引用來(lái)建立聯(lián)系。
支持的關(guān)系有:
* hasOne
* hasMany
* belongsTo
* belongsToMany
* embedsOne
* embedsMany
示例:
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class User extends Eloquent {
public function items(){
????return $this->hasMany('Item');
????}
}
和反比關(guān)系:
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Item extends Eloquent {
public function user(){
????return $this->belongsTo('User');
????}
}
belongsToMany關(guān)系不會(huì)使用數(shù)據(jù)透視表“table”,而是將id推送到related_ids屬性。 這使belongsToMany方法的第二個(gè)參數(shù)無(wú)用。 如果要為關(guān)系定義自定義鍵,請(qǐng)將其設(shè)置為null:
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class User extends Eloquent {
public function groups(){
????return $this->belongsToMany('Group', null, 'user_ids', 'group_ids');
????}
}
其他關(guān)系尚未得到支持,但未來(lái)可能會(huì)增加。 在http://laravel.com/docs/eloquent#relationships上閱讀有關(guān)這些關(guān)系的更多信息
EmbedsMany Relations
如果要嵌入模型而不是引用它們,可以使用embedsMany關(guān)系。 此關(guān)系類(lèi)似于hasMany關(guān)系,但將模型嵌入父對(duì)象中。
記住:這些關(guān)系返回Eloquent集合,它們不返回查詢(xún)構(gòu)建器對(duì)象!
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class User extends Eloquent {
public function books(){
????return $this->embedsMany('Book');
????}
}
您可以通過(guò)動(dòng)態(tài)屬性訪(fǎng)問(wèn)嵌入式模型:
$books = User::first()->books;
反向關(guān)系是自動(dòng)可用的,您無(wú)需定義此反向關(guān)系。
$user = $book->user;
插入和更新嵌入式模型的工作方式與hasMany關(guān)系類(lèi)似:
$book = new Book(['title' => 'A Game of Thrones']);
$user = User::first();
$book = $user->books()->save($book);
// or
$book = $user->books()->create(['title' => 'A Game of Thrones'])
您可以使用其保存方法更新嵌入式模型(從2.0.0版開(kāi)始提供):
$book = $user->books()->first();
$book->title = 'A Game of Thrones';
$book->save();
您可以通過(guò)在關(guān)系上使用destroy方法或模型上的delete方法(從2.0.0版開(kāi)始提供)來(lái)刪除嵌入式模型:
$book = $user->books()->first();
$book->delete();
// or
$user->books()->destroy($book);
如果要在不觸及數(shù)據(jù)庫(kù)的情況下添加或刪除嵌入式模型,可以使用關(guān)聯(lián)和分離方法。 要最終將更改寫(xiě)入數(shù)據(jù)庫(kù),請(qǐng)保存父對(duì)象:
$user->books()->associate($book);
$user->save();
與其他關(guān)系一樣,embedsMany根據(jù)模型名稱(chēng)假定關(guān)系的本地鍵。 您可以通過(guò)將第二個(gè)參數(shù)傳遞給embedsMany方法來(lái)覆蓋默認(rèn)本地鍵:
return $this->embedsMany('Book', 'local_key');
嵌入式關(guān)系將返回嵌入式項(xiàng)的集合,而不是查詢(xún)構(gòu)建器。 查看可用的操作:https://laravel.com/docs/master/collections
EmbedsOne Relations
embedsOne關(guān)系類(lèi)似于embedsMany關(guān)系,但只嵌入單個(gè)模型。
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Book extends Eloquent {
public function author(){
????return $this->embedsOne('Author');
????}
}
您可以通過(guò)動(dòng)態(tài)屬性訪(fǎng)問(wèn)嵌入式模型:
$author = Book::first()->author;
插入和更新嵌入式模型的工作方式與hasOne關(guān)系類(lèi)似:
$author = new Author(['name' => 'John Doe']);
$book = Books::first();
$author = $book->author()->save($author);
// or
$author = $book->author()->create(['name' => 'John Doe']);
您可以使用以下新模型替換嵌入式模型:
$author = $book->author;
$author->name = 'Jane Doe';
$author->save();
您可以使用以下新模型替換嵌入式模型:
$newAuthor = new Author(['name' => 'Jane Doe']);
$book->author()->save($newAuthor);
MySQL關(guān)系
如果您正在使用混合MongoDB和SQL設(shè)置,那么您很幸運(yùn)! 模型將根據(jù)相關(guān)模型的類(lèi)型自動(dòng)返回MongoDB或SQL關(guān)系。 當(dāng)然,如果您希望此功能雙向工作,則您的SQL模型將需要使用Jenssegers \ Mongodb \ Eloquent \ HybridRelations特性。 請(qǐng)注意,此功能僅適用于hasOne,hasMany和belongsTo關(guān)系。
示例基于SQL的用戶(hù)模型:
use Jenssegers\Mongodb\Eloquent\HybridRelations;
class User extends Eloquent {
use HybridRelations;
protected $connection = 'mysql';
public function messages(){
????return $this->hasMany('Message');
????}
}
而基于Mongodb的Message模型:
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Message extends Eloquent {
protected $connection = 'mongodb';
public function user(){
????return $this->belongsTo('User');
????}
}
原始表達(dá)
這些表達(dá)式將直接注入查詢(xún)中。
User::whereRaw(['age' => array('$gt' => 30, '$lt' => 40)])->get();
您還可以在內(nèi)部MongoCollection對(duì)象上執(zhí)行原始表達(dá)式。 如果在模型類(lèi)上執(zhí)行此操作,它將返回一組模型。 如果在查詢(xún)構(gòu)建器上執(zhí)行此操作,它將返回原始響應(yīng)。
//返回用戶(hù)模型的集合。
$models = User::raw(function($collection){
????return $collection->find();
});
//返回原始的MongoCursor。
$cursor = DB::collection('users')->raw(function($collection){
????return $collection->find();
});
可選:如果未將閉包傳遞給raw方法,則可以訪(fǎng)問(wèn)內(nèi)部MongoCollection對(duì)象:
$model = User::raw()->findOne(['age' => array('$lt' => 18)]);
可以像這樣訪(fǎng)問(wèn)內(nèi)部MongoClient和MongoDB對(duì)象:
$client = DB::getMongoClient();
$db = DB::getMongoDB();
MongoDB 具體操作
超時(shí)
要防止MongoCursorTimeout異常,您可以手動(dòng)設(shè)置將應(yīng)用于游標(biāo)的超時(shí)值:
DB::collection('users')->timeout(-1)->get();
Upsert是一種特殊的更新方式,要是沒(méi)有找到符合條件的文檔,則會(huì)自動(dòng)創(chuàng)建一個(gè)文檔,否則更新對(duì)應(yīng)的文檔數(shù)據(jù)。
看 mongodb權(quán)威指南提到 upsert會(huì)避免競(jìng)態(tài)問(wèn)題,如果使用日常的思維去考慮這個(gè)問(wèn)題,需要先去數(shù)據(jù)庫(kù)中查找符合條件的文檔,然后再根據(jù)更新信息更新數(shù)據(jù),這個(gè)在多線(xiàn)程或者多進(jìn)程的情況下產(chǎn)生資源競(jìng)爭(zhēng)的情況,使用 upsert可以很好的避免這種情況的發(fā)
DB::collection('users')->where('name', 'John')
->update($data, ['upsert' => true]);
Projections(投影文檔)
您可以使用項(xiàng)目方法將投影應(yīng)用于查詢(xún)。
value字段的取值為0或者false時(shí),表示要在返回結(jié)果中去除該字段;如果value字段取值為1或者true,表示在返回結(jié)果中需要包含這個(gè)字段。
查詢(xún)結(jié)構(gòu)只展示title和likes
$project = ['title'=>1,'likes'=>1,"_id"=>0];
DB::collection('users')->project($project)->get();
DB::collection('items')->project(['tags' => ['$slice' => 1]])->get();
DB::collection('items')->project(['tags' => ['$slice' => [3, 7]]])->get();
分頁(yè)使用
$limit = 25;
$projections = ['id', 'name'];
DB::collection('items')->paginate($limit, $projections);
Push(更新數(shù)組$push操作符)
$push操作符添加指定的值到數(shù)組中,$push操作符有如下的格式:
DB::collection('users')->where('name', 'John')->push('items', 'boots');
DB::collection('users')->where('name', 'John')->push('messages', ['from' => 'Jane Doe', 'message' => 'Hi John']);
如果您不想要重復(fù)項(xiàng),請(qǐng)將第三個(gè)參數(shù)設(shè)置為true:
DB::collection('users')->where('name', 'John')->push('items', 'boots', true);
Pull(更新數(shù)組$pull修飾符)
$pull修飾符會(huì)刪除掉數(shù)組中符合條件的元素
DB::collection('users')->where('name', 'John')->pull('items', 'boots');
DB::collection('users')->where('name', 'John')->pull('messages', ['from' => 'Jane Doe', 'message' => 'Hi John']);
Unset(刪除一個(gè)指定的字段)
如果指定的字段不存在則操作不做任何處理;
當(dāng)使用$操作符匹配任何數(shù)組元素,$unset替換指定的元素為null而不是刪除掉指定的元素,此行為保持?jǐn)?shù)組大小和位置一直;
從文檔中刪除一個(gè)或多個(gè)字段。
DB::collection('users')->where('name', 'John')->unset('note');
您還可以在模型上執(zhí)行取消設(shè)置。
$user = User::where('name', 'John')->first();
$user->unset('note');
查詢(xún)緩存
您可以使用remember方法輕松緩存查詢(xún)結(jié)果:
$users = User::remember(10)->get()
參考: http://laravel.com/docs/queries#caching-queries
查詢(xún)記錄
默認(rèn)情況下,Laravel會(huì)記錄已為當(dāng)前請(qǐng)求運(yùn)行的所有查詢(xún)的內(nèi)存。 但是,在某些情況下,例如插入大量行時(shí),這可能會(huì)導(dǎo)致應(yīng)用程序使用過(guò)多的內(nèi)存。 要禁用日志,可以使用disableQueryLog方法:
? ? DB::connection()->disableQueryLog();