3

mongo シェルを使用する場合、次のようなものを実行できます。

db.sandbox.insert({"line" : db.eval('storedFunction()') })
       or
db.sandbox.insert({"line" : function() {return 1337} })

PHPを使用して同じ効果を達成できませんでした。私がやりたいのは、次のようなものを実行することです

$fnc = "function() {return 123}";
$col = (new Mongo)->database->collection;
$col->insert(['col' => new MongoCode($fnc)]);

見つけて

{
   "_id" : ...., 
   "col" : 123
} 

コレクションで。どうすればこれを達成できますか?それは可能ですか?


さらに詳細が必要な場合は、オートインクリメントを模倣しようとしています。私が書いているこの関数は、増分フィールドの最後に使用された値を取得し、それをインクリメントして値を返し、挿入されるドキュメントに一意の値を割り当てる必要があります。

4

3 に答える 3

3

JavaScript 関数は BSON の第一級の型であるため (仕様を参照)、両方の例 (JS シェルと PHP) で、関数自体をフィールドに格納します。関数を評価する場合は、サーバー側の JavaScript を実行する必要があります。次の例を検討してください。

<?php

$m = new Mongo();
$db = $m->test;
$c = $db->foo;
$c->drop();

$f = 'function() { return 123; }';

$c->insert(['f' => new MongoCode($f)]);
var_dump($c->findOne()['f']);

$g = <<<'END'
    function() {
        var doc = db.foo.findOne();
        db.foo.update(
            { _id: doc._id },
            { $set: { f: doc.f() }}
        );
    }
END;

$db->execute(new MongoCode($g));

$c->insert(['f' => new MongoCode($f)]);
var_dump($c->findOne()['f']);

次の出力が得られます。

object(MongoCode)#7 (2) {
  ["code"]=>
  string(26) "function() { return 123; }"
  ["scope"]=>
  array(0) {
  }
}
float(123)

関数が何らかの外部状態に依存している場合 (例: 結果を計算するためにクエリを実行する必要がある場合)、別のフィールドに保存し、ドキュメントを定期的に繰り返し、別のフィールドを更新して出力を保持する必要があります。これを実装するときは、サーバー側のコード評価にはいくつかの同時実行制限があることに注意してください。

于 2012-08-03T14:59:55.173 に答える
1

正確には、MongoDB でやりたいことを行うことはできません。シェルで例を実行すると、db.eval...最初にビットが呼び出され、次に計算結果がドキュメントの一部として渡されます。書き込み操作中に Mongo が評価する唯一のものは、更新 (または必要に応じてアップサート) の一部としての特別な修飾子フィールドです。ただし、コレクションごとのカウンターを実行できるものはありません。

自動インクリメントの場合、2 つのクエリを実行する必要があります。を使用findAndModifyして、数値をアトミックにインクリメントして取得し、それをlines値に割り当てることができます。

シェルから行う方法は次のとおりです。

counter = db.counters.findAndModify({
  query: {_id: "line-counter"}, 
  update: {$inc: {value: 1}}, 
  new: true, 
  upsert: true}).value
db.sandbox.insert({line: counter})
于 2012-08-07T20:25:15.010 に答える
1

あなたは強化フィールドを作ろうとしているので、間違っていると言わせてください。

@jmikola が述べているように、サーバー側の評価には深刻な問題があり、シャーディングを含むすべてのものとほぼ互換性がないという事実が含まれています。実際、サーバー側の実行についてはあまり学習しないことをお勧めします。そのため、その方法の例を示すことさえしません。

JS のサーバー側での実行から離れることをお勧めします。これは、SQL のストアド プロシージャやトリガーとは異なり、実際には同じようには実行されません。JS コンソールは、MySQL コンソールによく似た単なる別のドライバーであり、これが混乱を招いていると思います。コンソールはサーバー側の実行 (ストアド プロシージャなど) のようなものだと考える人もいますが、そうではありません。別のクライアント。

Map Reduce は、実際にサポートされている唯一の「サーバー側」の実行です。もちろん、将来の使用のために system.js 内にスクリプトを保存することもできますが、これは面倒な MR スクリプトを DB 内に保存するように設計されているため、頻繁にスクリプトを書き込んだり、巨大なファイルをネットワーク経由で繰り返し送信したりする必要はありません。

私が書いているこの関数は、増分フィールドの最後に使用された値を取得する必要があります

この関数は、別の挿入によって既に使用されている可能性があるため、同時実行によりその新しい ID が無効になるため、期待どおりに機能しないことは間違いありません。もちろん、これは挿入の頻度に依存しますが、わずかな負荷でも ID は正しく増加しません。

自動インクリメント ID を実現するには、実際に次のように findandmodify を使用できます: http://www.mongodb.org/display/DOCS/How+to+Make+an+Auto+Incrementing+Fieldおよび @MrKurts 回答内。

于 2012-08-13T13:13:53.610 に答える