3

csv ファイルからインポートされた非常に大きなデータベース (〜 600 万行) があります。私は MongoDB と GeoSpatial インデックス作成に関するドキュメントを見ていました。配列に埋め込まれた緯度と経度のフィールドが必要です。残念ながら、インポートした構造にはフィールドが分​​かれています。

「緯度」:54.770233、「経度」:-6.537741、

54 の緯度と -6 の経度を使用して、半径 25 マイル以内にある 20 個の最も近いドキュメントを計算するために DB にクエリを実行する方法はありますか?

MySQL でクエリを作成しました:

SELECT * , ( 3959 * ACOS( COS( RADIANS( 54 ) ) * COS( RADIANS( latitude) ) * COS( RADIANS( longitude) - RADIANS( -6 ) ) + SIN( RADIANS( 54 ) ) * SIN( RADIANS( latitude) ) ) ) AS 距離 FROM テーブル名 HAVING 距離 <25 ORDER BY 距離 LIMIT 0 , 20

ただし、埋め込みフィールドなしで Mongo でこれを行う方法がわかりません。

どんな助けでも大歓迎です。

4

1 に答える 1

3

私はあなたができるとは思わない。スクリプトを実行して、すべてのドキュメントを調べて更新します。これにはしばらく時間がかかりますが、それほど長くはありません。次に、通常どおり 2D インデックスを作成できます。

> db.test.insert({latitude:73,longitude:-47});
> db.test.insert({latitude:20,longitude:-30});
> db.test.find().forEach(function(doc) {
  doc.loc = [doc.longitude, doc.latitude];
  db.test.save(doc);
});
> db.test.find();
{ "_id" : ObjectId("4f7c63f117cd93783bba936d"), "latitude" : 73, "longitude" : -47, "loc" : [ 73, -47 ] }
{ "_id" : ObjectId("4f7c63f817cd93783bba936e"), "latitude" : 20, "longitude" : -30, "loc" : [ 20, -30 ] }

更新された実際には、where句を使用して実行できると思いますが、インデックスは使用しません。ただし、1 回限りのクエリの場合は、おそらく問題ありません。

db.test.find("( 3959 * Math.acos(Math.cos( 54 * 0.0174532925 ) * Math.cos( this.latitude * 0.0174532925 ) * Math.cos( this.longitude * 0.0174532925 ) - (-6 * 0.0174532925)) + Math.sin( 54 * 0.0174532925 ) * Math.sin( this.latitude * 0.0174532925 )) > 25 ");

これは実際には機能しません。計算結果が大きすぎます。私はちょうどあなたの数学を真似しようとしていたのですが、何かが間違っていたに違いありません。いずれにせよ、距離によるソートも問題になるでしょう。最初の解決策は少し扱いやすいと思います。

于 2012-04-04T15:11:42.063 に答える