laravel MongoDB 的使用

MongoDB 条件操作符

Exists(判断字段是否存在)

查询所有存在age字段的记录

User::where('age', 'exists', true)->get();

查询所有不存在name字段的记录

User::where('age', 'exists', false)->get();

All(匹配所有)

这个操作符跟SQL语法的in类似,但不同的是, in只需满足( )内的某一个值即可,而$all必须满足[ ]内的所有值

User::where('roles', 'all', ['moderator', 'author'])->get();

Size(数组元素个数)

对于查询数组来说是非常有用的,顾名思义,可以用它查询特定长度的数组。

User::where('tags', 'size', 3)->get();

Regex(正则表达式匹配)

选择值与指定正则表达式匹配的文档。

User::where('name', 'regex', new \MongoDB\BSON\Regex("/.*doe/i"))->get();

注意:您也可以使用Laravel正则表达式操作。 这些更灵活,会自动将正则表达式字符串转换为MongoDB \ BSON \ Regex对象。

User::where('name', 'regexp', '/.*doe/i'))->get();

反之:

User::where('name', 'not regexp', '/.*doe/i'))->get();

Type(类型)

User::where('age', 'type', 2)->get();

Mod(取模运算)

查询age取模10等于0的数据

User::where('age', 'mod', [10, 0])->get();

Near(指定地理空间查询从最近到最远返回文档的点。)

$ near运算符可以指定GeoJSON点或传统坐标点。

$users = User::where('location', 'near', [

        '$geometry' => [

        'type' => 'Point',

        'coordinates' => [

                -0.1367563,

                51.5100913,

            ],

        ],

        '$maxDistance' => 50,

]);

GeoWithin(选择具有完全在指定形状内的地理空间数据的文档。)

$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(选择地理空间数据与指定GeoJSON对象相交的文档;即数据和指定对象的交集是非空的。)

$locations = Location::where('location', 'geoIntersects', [

'$geometry' => [

        'type' => 'LineString',

        'coordinates' => [

            [-0.144044,51.515215,],[-0.129545,51.507864,],

        ],

        ],

    ]);

Where

匹配满足JavaScript表达式的文档。 有关更多信息,请查看 http://docs.mongodb.org/manual/reference/operator/query/where/#op._S_where

Inserts, updates and deletes

插入,更新和删除记录就像原始的Eloquent一样。

通过模型插入数据

$user = new User;

$user->name = 'John';

$user->save();

您还可以使用create方法将新模型保存在一行中:

User::create(['name' => 'John']);

通过模型更新数据

要更新模型,您可以检索它,更改属性并使用save方法。

$user = User::first();

$user->email = 'john@foo.com';

$user->save();

通过模型删除数据

要删除模型,只需在实例上调用delete方法:

$user = User::first();

$user->delete();

或者通过主键删除

User::destroy('517c43667db388101e00000f');

Dates

Eloquent允许您使用Carbon / DateTime对象而不是MongoDate对象。 在内部,这些日期在保存到数据库时将转换为MongoDate对象。 如果您希望在非默认日期字段中使用此功能,则需要按照此处所述手动指定它们: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 关系

MongoDB的关系表示多个文档之间在逻辑上的相互联系文档间可以通过嵌入和引用来建立联系。

支持的关系有:

* hasOne

* hasMany

* belongsTo

* belongsToMany

* embedsOne

* embedsMany

示例:

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class User extends Eloquent {

public function items(){

    return $this->hasMany('Item');

    }

}

和反比关系:

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class Item extends Eloquent {

public function user(){

    return $this->belongsTo('User');

    }

}

belongsToMany关系不会使用数据透视表“table”,而是将id推送到related_ids属性。 这使belongsToMany方法的第二个参数无用。 如果要为关系定义自定义键,请将其设置为null:

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class User extends Eloquent {

public function groups(){

    return $this->belongsToMany('Group', null, 'user_ids', 'group_ids');

    }

}

其他关系尚未得到支持,但未来可能会增加。 在http://laravel.com/docs/eloquent#relationships上阅读有关这些关系的更多信息

EmbedsMany Relations

如果要嵌入模型而不是引用它们,可以使用embedsMany关系。 此关系类似于hasMany关系,但将模型嵌入父对象中。

记住:这些关系返回Eloquent集合,它们不返回查询构建器对象!

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class User extends Eloquent {

public function books(){

    return $this->embedsMany('Book');

    }

}

您可以通过动态属性访问嵌入式模型:

$books = User::first()->books;

反向关系是自动可用的,您无需定义此反向关系。

$user = $book->user;

插入和更新嵌入式模型的工作方式与hasMany关系类似:

$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版开始提供):

$book = $user->books()->first();

$book->title = 'A Game of Thrones';

$book->save();

您可以通过在关系上使用destroy方法或模型上的delete方法(从2.0.0版开始提供)来删除嵌入式模型:

$book = $user->books()->first();

$book->delete();

// or

$user->books()->destroy($book);

如果要在不触及数据库的情况下添加或删除嵌入式模型,可以使用关联和分离方法。 要最终将更改写入数据库,请保存父对象:

$user->books()->associate($book);

$user->save();

与其他关系一样,embedsMany根据模型名称假定关系的本地键。 您可以通过将第二个参数传递给embedsMany方法来覆盖默认本地键:

return $this->embedsMany('Book', 'local_key');

嵌入式关系将返回嵌入式项的集合,而不是查询构建器。 查看可用的操作:https://laravel.com/docs/master/collections

EmbedsOne Relations

embedsOne关系类似于embedsMany关系,但只嵌入单个模型。

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class Book extends Eloquent {

public function author(){

    return $this->embedsOne('Author');

    }

}

您可以通过动态属性访问嵌入式模型:

$author = Book::first()->author;

插入和更新嵌入式模型的工作方式与hasOne关系类似:

$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关系

如果您正在使用混合MongoDB和SQL设置,那么您很幸运! 模型将根据相关模型的类型自动返回MongoDB或SQL关系。 当然,如果您希望此功能双向工作,则您的SQL模型将需要使用Jenssegers \ Mongodb \ Eloquent \ HybridRelations特性。 请注意,此功能仅适用于hasOne,hasMany和belongsTo关系。

示例基于SQL的用户模型:

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');

    }

}

原始表达

这些表达式将直接注入查询中。

User::whereRaw(['age' => array('$gt' => 30, '$lt' => 40)])->get();

您还可以在内部MongoCollection对象上执行原始表达式。 如果在模型类上执行此操作,它将返回一组模型。 如果在查询构建器上执行此操作,它将返回原始响应。

//返回用户模型的集合。

$models = User::raw(function($collection){

    return $collection->find();

});

//返回原始的MongoCursor。

$cursor = DB::collection('users')->raw(function($collection){

    return $collection->find();

});

可选:如果未将闭包传递给raw方法,则可以访问内部MongoCollection对象:

$model = User::raw()->findOne(['age' => array('$lt' => 18)]);

可以像这样访问内部MongoClient和MongoDB对象:

$client = DB::getMongoClient();

$db = DB::getMongoDB();

MongoDB 具体操作

超时

要防止MongoCursorTimeout异常,您可以手动设置将应用于游标的超时值:

DB::collection('users')->timeout(-1)->get();

Upsert是一种特殊的更新方式,要是没有找到符合条件的文档,则会自动创建一个文档,否则更新对应的文档数据。

看 mongodb权威指南提到 upsert会避免竞态问题,如果使用日常的思维去考虑这个问题,需要先去数据库中查找符合条件的文档,然后再根据更新信息更新数据,这个在多线程或者多进程的情况下产生资源竞争的情况,使用 upsert可以很好的避免这种情况的发

DB::collection('users')->where('name', 'John')

->update($data, ['upsert' => true]);

Projections(投影文档)

您可以使用项目方法将投影应用于查询。

value字段的取值为0或者false时,表示要在返回结果中去除该字段;如果value字段取值为1或者true,表示在返回结果中需要包含这个字段。

查询结构只展示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();

分页使用

$limit = 25;

$projections = ['id', 'name'];

DB::collection('items')->paginate($limit, $projections);

Push(更新数组$push操作符)

$push操作符添加指定的值到数组中,$push操作符有如下的格式:

DB::collection('users')->where('name', 'John')->push('items', 'boots');

DB::collection('users')->where('name', 'John')->push('messages', ['from' => 'Jane Doe', 'message' => 'Hi John']);

如果您不想要重复项,请将第三个参数设置为true:

DB::collection('users')->where('name', 'John')->push('items', 'boots', true);

Pull(更新数组$pull修饰符)

$pull修饰符会删除掉数组中符合条件的元素

DB::collection('users')->where('name', 'John')->pull('items', 'boots');

DB::collection('users')->where('name', 'John')->pull('messages', ['from' => 'Jane Doe', 'message' => 'Hi John']);

Unset(删除一个指定的字段)

如果指定的字段不存在则操作不做任何处理;

当使用$操作符匹配任何数组元素,$unset替换指定的元素为null而不是删除掉指定的元素,此行为保持数组大小和位置一直;

从文档中删除一个或多个字段。

DB::collection('users')->where('name', 'John')->unset('note');

您还可以在模型上执行取消设置。

$user = User::where('name', 'John')->first();

$user->unset('note');

查询缓存

您可以使用remember方法轻松缓存查询结果:

$users = User::remember(10)->get()

参考: http://laravel.com/docs/queries#caching-queries

查询记录

默认情况下,Laravel会记录已为当前请求运行的所有查询的内存。 但是,在某些情况下,例如插入大量行时,这可能会导致应用程序使用过多的内存。 要禁用日志,可以使用disableQueryLog方法:

    DB::connection()->disableQueryLog();

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容