nazolabo

フリーランスのWebエンジニアが近況や思ったことを発信しています。

PHPでMongoDBを使ってみる その2

http://www.nyphp.org/PHP-Presentations/145_Recovering-Mongos-MongoDB-PHP
これが参考になる

=以外の条件

<?php

$mongo = new Mongo();

$col = $mongo->selectDB( "foo" )->selectCollection( "bar" );

$data = array("name" => "foo", "num" => 1);
$col->insert( $data );
$data = array("name" => "bar", "num" => 2);
$col->insert( $data );
$data = array("name" => "baz", "num" => 3);
$col->insert( $data );

$cursor = $col->find(array('num' => array('$gt' => 1)));
foreach ($cursor as $id =>$obj) {
        var_dump( $obj );
}

$gtとか$ltとかで条件指定するらしい、""で囲むとPHPの変数扱いされるので''で。
ちなみにこの$はphp.iniのmongo.cmdで変更できる。

$gt >
$lt
$gte >=
$lte <=
$ne !=
$in SQLのINと同じ
$nin NOT IN
$mod array(x, y)と指定した場合、対象をxで割った余りが1かどうか
$all 集合を全て含むかどうか
$size 要素の数
$exists フィールドが存在するかどうか(true/false)

詳しくは
http://www.mongodb.org/display/DOCS/Advanced+Queries

文字列の部分一致

正規表現が使える

<?php
//このへんまで上のと同じ

$cursor = $col->find(array('name' => new MongoRegex('/ba/i')));
foreach ($cursor as $id =>$obj) {
        var_dump( $obj );
}

MongoRegexオブジェクトを作らないといけないのがちょっと面倒(言語によってはそのままいけるらしい)

SQLっぽい条件指定

SQLインジェクションの恐怖再び

$cursor = $col->find(array('$where' => 'this.num > 1'));

this.何とかで、自分の値を取れるので、this.x + this.y > 1とかもできる。

JavaScript条件

MongoDBはJavaScriptエンジンを内蔵しているので、

$cursor = $col->find(array('$where' => 'this.num > Math.abs(-1)'));

こういうことができる。
単にJavaScriptを実行してほしいだけなら

<?php
$mongo = new Mongo();
$db = $mongo->selectDB( "foo" );
$code = new MongoCode("function() { return 'hello'; }");
$ret = $db->execute($code);
var_dump($ret);

これで、array('retval' => 'hello', 'ok' => 1)が返ってくる。
JSに対してPHPから引数を与えたい場合は、

<?php

$mongo = new Mongo();
$db = $mongo->selectDB( "foo" );
$code = new MongoCode("function() { return x + 1; }", array("x" => 1));
$ret = $db->execute($code);
var_dump($ret);

深い階層の条件指定

<?php

$mongo = new Mongo();

$col = $mongo->selectDB( "foo" )->selectCollection( "bar" );

$data = array("name" => "foo", "data" => array('a' => 1, 'b' => 10));
$col->insert( $data );
$data = array("name" => "bar", "data" => array('a' => 2, 'b' => 20));
$col->insert( $data );
$data = array("name" => "baz", "data" => array('a' => 3, 'b' => 30));
$col->insert( $data );

$cursor = $col->find(array('data.a' => 1));
foreach ($cursor as $id =>$obj) {
        var_dump( $obj );
}

ドットで繋ぐ。

ページング的な処理

LIMITとOFFSET的な(上の資料からコピペ)

$page_num= 3;
$results_per_page= 10;
$cursor = $results->find()
                  ->sort(array("ts" => -1))
                  ->skip($page_num * $results_per_page)
                  ->limit($results_per_page);

skipがoffset、limitはlimitで。

おまけ

MongoDBをO/Rマッパ的に使うライブラリMorph
http://code.google.com/p/mongodb-morph/
なんかメリット殺してるような気がしなくも…。でも楽かもしれない