web-dev-qa-db-ja.com

マングースでGeoLocationを作成して検索する

場所の経度/緯度をユーザーモデルに保存し、_$geoNear_でクエリしようとしています。私はそのトピックについて見つけることができるほとんどすべてのページを見てきましたが、それでも1)適切にモデルを作成する方法とそれをクエリする方法がわかりません。

これが私のモデルの一部です:

_loc: {
        //type: 'Point', // see 1
        //type: String, // see 2
        coordinates: [Number],
        index: '2dsphere' // see 3
    },
_

@ 1:ドキュメントによると、ポイントを保存する場合、タイプは「ポイント」である必要がありますが、スローされます

_TypeError: Undefined type `Point` at `loc`
  Did you try nesting Schemas? You can only nest using refs or arrays.
_

私はそれがStringであるべきだと思うので、これは理にかなっています

@ 2:これはすぐにエラーをスローしませんが、ユーザーを保存しようとすると次のようになります。

_name: 'ValidationError',
  errors: 
   { loc: 
      { [CastError: Cast to String failed for value "[object Object]" at path "loc"]
_

@ 3:そのようなインデックスを作成したい場合、エラーが発生します:

_TypeError: Undefined type `2dsphere` at `loc.index`
  Did you try nesting Schemas? You can only nest using refs or arrays.
_

だから私はこのように私に少し適切に感じたものにインデックスを保存しようとしました:

_userSchema.index({'loc': '2dsphere'});
_

新しいユーザーを保存しようとすると、次のエラーがスローされます。

_- { [MongoError: Can't extract geo keys from object, malformed geometry?:{ coordinates: [ -73.97, 40.77 ] }]
  name: 'MongoError',
  message: 'Can\'t extract geo keys from object, malformed geometry?:{ coordinates: [ -73.97, 40.77 ] }',
  ok: 1,
  n: 0,
  code: 16572,
  errmsg: 'Can\'t extract geo keys from object, malformed geometry?:{ coordinates: [ -73.97, 40.77 ] }',
  writeConcernError: 
   { code: 16572,
     errmsg: 'Can\'t extract geo keys from object, malformed geometry?:{ coordinates: [ -73.97, 40.77 ] }' } }
MongoError: Can't extract geo keys from object, malformed geometry?:{ coordinates: [ -73.97, 40.77 ] }
_

データベースのモデルを_$geoNear_コマンドに更新したとき、ユーザーを次のように更新しました。

_loc: {coordinates: [-73.97, 40.77]}
_

次のように正常にクエリできます:

_ mongoose.model('users').db.db.command({
    "geoNear": users,
    "near": [
        <latitude>,
        <longitude>
    ],
    "spherical": true,
    "distanceMultiplier": 6378.1, // multiplier for kilometres
    "maxDistance": 100 / 6378.1, // every user within 100 km
    "query": { }
_

find()を使用すると_$geoNear_が利用できないため、db.commandを使用しました)

私がこれまでに試みたすべてのことは私をどこにも導いてくれなかったので、私の質問は今です:

  • マングースモデルはどのように見えるのですか?
  • データベースにユーザーの場所を保存するにはどうすればよいですか

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

13
Markus

スキーマでGeoJSONをサポートする場合は、まずそれを適切に構築する必要があります。

_var userSchema = new Schema({
    loc: {
        type: { type: String },
        coordinates: [Number],
    }
});
_

これにより、スキーマ定義の「type」キーワードとの混乱がなくなります。 GeoJSONタイプの全範囲を本当にサポートしたい場合は、少し緩くすることができます。

_var userSchema = new Schema({
    loc: {
        type: { type: String },
        coordinates: []
    }
});
_

次に、インデックスをスキーマに結び付けます。

_userSchema.index({ "loc": "2dsphere" });
_

次に、もちろんモデルを定義して、正しく保存します。

_var User = mongoose.model( "User", userSchema );

 var user = new User({ 
     "loc": { 
         "type": "Point",
         "coordinates": [-73.97, 40.77]
     }
 });
_

データはlongitudeで、次にlatitudeの順序である必要があることに注意してください。 GeoJSONおよびすべてのMongoDB地理空間クエリフォーム。

次に、rawドライバーメソッドで直接データベースコマンドのあいまいな使用法を掘り下げるのではなく、直接サポートされているものを使用してください。 _$geoNear_ などの.aggregate()メソッドの場合:

_User.aggregate(
    [
        { "$geoNear": {
            "near": {
                "type": "Point",
                "coordinates": [<long>,<lat>]
            },
            "distanceField": "distance",
            "spherical": true,
            "maxDistance": 10000
        }}
    ],
    function(err,results) {

    }
)
_

また、データがGeoJSONであるため、距離はすでにメートルに変換されているため、他の変換作業を行う必要はありません。

また、これをいじくり回していることに注意してください。コレクションをドロップしない限り、試行したインデックスはまだそこにあり、問題が発生する可能性があります。

Mongodbシェルのコレクションからすべてのインデックスを簡単に削除できます:

_db.users.dropIndexes();
_

または、データの再整形が必要になる可能性が高いため、コレクションを削除して、もう一度開始します。

_db.users.drop();
_

正しくセットアップすれば問題はありません。

52
Blakes Seven