2016-04-18 7 views
2

私はユーザーの近接性に基づいてマッチングシステムを作成しています。基本的なアイデアは、ポイントAにはユーザーAがあり、ポイントBにはユーザーBがいるということです。両方のユーザーには、ユーザーがマッチを作るまでの距離を決定する検索フィルターがあります。この距離はキロメートルです。 A crude depiction地理空間クエリを作成してお互いの半径内に2人のユーザーを見つけよう

とにかく、これをバニラクエリ(集約クエリを使用せずに)で行うことは可能でしょうか?これまでのクエリはここにあります

var loc = userA.location; 
var rad = userA.radius; 

{$near : { 
     $geometry : { 
      type : "Point", 
      coordinates : loc 
     }, 
     $maxDistance : rad 
    } 
} 

私はどのようにユーザーのBの設定を考慮しますか?

私は基本的に好みのサークルだったジオメトリを保存し、userAがそのサークル内にあるかどうかを確認する予定でしたが、これはちょうど正しいとは思われません。

答えて

2

ことは良いことですので、あなたはすでに、ユーザーごとに保存されているradius性質を持っている、と$maxDistanceオプションのため、だけでなく、ユーザーとの距離が「未満」であるかどうかを確認するためのチェックとしてだけではなく、 radius属性。

これで基本的に必要なのは、その距離を見て比較する方法です。

db.users.aggregate([ 
    { "$geoNear": { 
     "near": { 
      "type": "Point", 
      "coordinates": userA.location 
     }, 
     "spherical": true, 
     "maxDistance": userA.radius, 
     "distanceField": "distance" 
    }}, 
    { "$redact": { 
     "$cond": { 
      "if": { "$lt": [ "$distance", "$radius" ] }, 
      "then": "$$KEEP", 
      "else": "$$PRUNE" 
     } 
    }} 
]) 

だから、これはそれが"maxDistance"制約と一緒に$near結果の同じ種類を実行しないものを、実際の間の実際の距離を表す名前の"distanceField"に追加のプロパティを返します。このためには、集約フレームワークと$geoNearを使用します「ユーザー」が見つかりました。インデックスが"2dsphere"の場合は、"spherical"オプションが必要です。

集約「パイプライン」として、これにより、別の操作が出力に作用することができます。 $redactステージは、既存の"radius"データと生成された"distance"フィールドの「論理比較」を行い、その距離が格納された半径データよりも小さいかどうかを確認します。その条件がtrueあるのみ

は、そうでなければ、距離が文書が$$PRUNE介して結果から除去されるように、ユーザーは半径よりも大きい、文書が$$KEEPを介して返されます。

これは結果を返すためのユーザーデータのradiusを尊重した比較方法です。

+0

ニールありがとう、これは素晴らしい答えです。あなたが気にしない最後の質問が1つありますが、私は半径フィールドをメートルで表しています。このクエリを実行すると、$ distanceフィールドは本当に小さな数字になります。 [docs](https://docs.mongodb.org/manual/reference/operator/aggregation/geoNear/)には言及していないようです。彼らはラジアンですか? –

+0

@naughtyboy実際の座標はどのように保存されていますか? GeoJSON形式の場合、返される「距離」は実際にはメートルです。しかし、そうでなければラジアンから変換する必要があり、同様に「maxDistance」にも当てはまります。数式を追加することはできますが、代わりにGeoJSONにデータを変換する方がずっと簡単で便利です。 –

+0

うーん、私は間違いなくメートルを扱うことを好むだろう。データはGeoJSONに 'loc:{type:" Point "、座標:[-80.5863052,22.7906625]、半径:500'として保存されます。座標は 'long、lat'形式で、半径はメートルで、' {loc: '2dsphere'} 'というフィールドにインデックスを作成しました。私が何かを見逃しているのかわからないのですか? –

関連する問題