私は mongodb と map-reduce を初めて使用し、k-means 空間クラスタリングを使用して空間データを評価したいと考えています。アルゴリズムの適切な説明と思われるこの記事を見つけましたが、これを mongo シェル スクリプトに変換する方法がわかりません。データが次のようになっているとします。
{
_id: ObjectID(),
loc: {x: <longitude>, y: <latitude>},
user: <userid>
}
{ k = sqrt(n/2) } を使用できます。n はサンプル数です。集計を使用して、データとカウントなどの境界範囲を取得できます。クラスター ポイントのファイルへの参照で迷子になりました。これは単なる別のコレクションであると想定しており、どうすればよいかわかりません。反復またはそれがクライアントまたはデータベースで行われるか?
OK、map-reduce フェーズで最小二乗和を計算する必要がある初期ランダム ポイントの配列を生成したという点で少し進歩しましたが、これらをに渡す方法がわかりません。マップ機能。私は map 関数を書くことに挑戦しました:
var mapCluster = function() {
var key = -1;
var sos = 0;
var pos;
for (var i=0; i<pts.length; i++) {
var dx = pts[i][0] - this.arguments.pos[0];
var dy = pts[i][1] - this.arguments.pos[1];
var sumOfSquare = dx*dx + dy*dy;
if (i == 0 || sumOfSquares < sos) {
key = i;
sos = sumOfSquares;
pos = this.arguments.pos;
}
}
emit(key, pos);
};
この場合、クラスターポイントは次のようになりますが、おそらく機能しません。
var pts = [ [x,y], [x1,y1], ... ];
したがって、各 mr 反復では、すべてのコレクション ポイントをこの配列と比較し、最も近いポイントのインデックスとコレクション ポイントの位置を出力します。reduce 関数では、各インデックスに関連付けられたポイントの平均は次のようになります。新しいクラスター ポイントの場所を作成するために使用されます。その後、finialize 関数でクラスター ドキュメントを更新できます。
クラスタ ドキュメントで findOne() を実行してクラスタ ポイントを map 関数にロードできると思いますが、map を呼び出すたびにこのドキュメントをロードしますか? または、反復ごとに1回ロードする方法はありますか?
したがって、次のようにスコープ変数を使用して上記を実行できるようです。
db.main.mapReduce( mapCluster, mapReduce, { scope: { pnts: pnts, ... }} );
これらは既存の変数名と衝突する可能性がある map、reduce、および finalize 関数のスコープに配置されるため、スコープ内の変数名には注意する必要があります。