2016-06-09 28 views
12

Mam problem, którego nie udało mi się rozwiązać za kilka dni, nawet patrząc na powiązany Stack Overflow Q/ZA.Wyszukiwanie najbliższych punktów do określonego punktu ze współrzędnymi i maksymalną odległością - Wynik kwerendy Nieokreślony przy użyciu Mongoose ze stosem MEAN

Opracowuję aplikację ponownie korzystającą z podejścia Scotch's Create a MEAN Stack Google Map App Tutorial by Ahmed Haque.

próbuję wdrożyć aplikację, która wykorzystuje Google Maps API zwrócić Points, LineStrings i Polygons których współrzędne są zawarte w GeoJSON plików, które są przechowywane w MongoDB instancji.

Używam Mongoose do zbudowania schematu dla moich danych i zapytania do bazy danych MongoDB.

chciałbym znaleźć najbliższymi punktami CP do pewnych punktach P0 podane P0's latitude and longitude i podanych maksymalny promień distance używany znaleźć zainteresowanych punktów.

enter image description here

Biorąc pod uwagę obraz na pragnę, że, na przykład, jeśli wstawić 2000 (kilometry), moja kwerenda będzie znaleźć wszystkie punkty maksymalne 2000 kilometrów od P0. W tym przykładzie powinien prawdopodobnie dać mi P1 i P2.

Udało mi się to zrobić, gdy miałem tylko punkty w moim Mongoose Schema.

miałem ten Schema z tylko markerów (punktów):

// Pulls Mongoose dependency for creating schemas 
var mongoose = require('mongoose'); 
var Schema  = mongoose.Schema; 

// Creates a User Schema. 
var MarkerSchema = new Schema({ 
    username: {type: String, required: true}, 
    location: {type: [Number], required: true}, // [Long, Lat] 
    created_at: {type: Date, default: Date.now}, 
    updated_at: {type: Date, default: Date.now} 
}); 

// Indexes this schema in 2dsphere format 
MarkerSchema.index({location: '2dsphere'}); 

module.exports = mongoose.model('mean-markers', MarkerSchema); 

i to był mój Old Query for only Markers:

var User = require('./model.js'); 

app.post('/query/', function(req, res) { 

     // Grab all of the query parameters from the body. 
     var lat = req.body.latitude; 
     var long = req.body.longitude; 
     var distance = req.body.distance; 
     var reqVerified = req.body.reqVerified; 

     // Opens a generic Mongoose Query 
     var query = User.find({}); 

     // ...include filter by Max Distance (converting miles to meters) 
     if (distance) { 

      // Using MongoDB's geospatial querying features 
      query = query.where('location').near({ 
       center: { 
        type: 'Point', 
        coordinates: [long, lat] 
       }, 

       // Converting meters to miles 
       maxDistance: distance * 1609.34, 
       spherical: true 
      }); 
     } 
}); 

działało bardzo dobrze i udało mi się dostać blisko punktów.

Następnie zmieniono mój Schema, aby był bardziej dynamiczny, a także obsługuje Polylines and Polygons.

jestem w stanie włożyć i wyciągnąć nowe punkty, krzywe i wielokąty o następującej Schema:

var mongoose = require('mongoose'); 
var GeoJSON = require('geojson'); 
var Schema = mongoose.Schema; 

// Creates a Location Schema. 
var LocationSchema = new Schema({ 
            name: {type: String, required: true}, 
            location: { 
             type: {type : String, required: true}, 
             coordinates : [Schema.Types.Mixed] 
            }, 
            created_at: {type: Date, default: Date.now}, 
            updated_at: {type: Date, default: Date.now} 
}); 

LocationSchema.index({location: '2dsphere'}); 
module.exports = mongoose.model('mean-locations', LocationSchema); 

a to mój Mongoose Query:

var GeoObjects = require('./model.js'); 

app.post('/query/', function(req, res) { 

    // Grab all of the query parameters from the body. 
    var lat = req.body.latitude; 
    var long = req.body.longitude; 
    var distance = req.body.distance; 

    var query; 

    if (distance) { 
     query = GeoObjects.find({'location.type':'Point'}) 
        .where('location.coordinates').near({ 
         center: { 
         type: 'Point', 
         coordinates: [lat, long] 
         }, 
         // Converting meters to miles 
         maxDistance: distance * 1609.34, 
         spherical: true 
     }); 
    } 

    // Execute Query and Return the Query Results 
    query.exec(function(err, users) { 
     if (err) 
      res.send(err); 
     console.log(users); 
     // If no errors, respond with a JSON of all users that meet the criteria 
     res.json(users); 
    }); 
}); 

console.log(users); daje mi undefined.

Kwerenda rejestrowania wyników w moim queryCtrl.js daje mi następujący komunikat:

name: "MongoError", message: "error processing query: ns=MeanMapApp.mean-locatio…ed error: unable to find index for $geoNear query", waitedMS: 0, ok: 0, errmsg: "error processing query: ns=MeanMapApp.mean-locatio…ed error: unable to find index for $geoNear query"

samo z małej zmienności:

app.post('/query/', function(req, res) { 

    // Grab all of the query parameters from the body. 
    var lat = req.body.latitude; 
    var long = req.body.longitude; 
    var distance = req.body.distance; 

    console.log(lat,long,distance); 

    var points = GeoObjects.find({'location.type':'Point'}); 

    var loc = parseFloat(points.location.coordinates); 
    console.log(JSON.stringify(loc)); 

    if (distance) { 
     var query = points.near(loc, { 
         center: { 
         type: 'Point', 
         coordinates: [parseFloat(lat), parseFloat(long)] 
         }, 
         // Converting meters to miles 
         maxDistance: distance * 1609.34, 
         spherical: true 
     }); 
    } 
}); 

To jest przykładem markera:

{ 
    "name": "user01", 
    "location": { 
       "type":"Point", 
       "coordinates": [102.0, 0.0] 

    } 
} 

Jak $ near op Erator współpracuje z odległością i maxDistance:

Od Scotch's Making MEAN Apps with Google Maps (Part II) by Ahmed Haque

wyszukiwania MongoDB Parametr $ koło i związanych z nią właściwości maxDistance i sferycznych, aby określić zakres patrzymy na pokrycie. Mnożymy odległość naszego ciała zapytania przez 1609.34, ponieważ chcemy pobrać dane od naszych użytkowników (w milach) i przekonwertować je na jednostki , które MongoDB spodziewa się (w metrach).

  1. Dlaczego otrzymuję undefined?
  2. Czy to możliwe, że przyczyną problemu jest mój schemat?
  3. Jak mogę to naprawić?

Jeśli chcesz uzyskać jakieś wyjaśnienia, opublikuj komentarz poniżej.

Dzięki z góry.

+1

Hey @ AndreaM16. Czy masz szansę na ten kod na GitHub lub coś takiego, abyśmy mogli go ściągnąć i przyjrzeć mu się bliżej? –

+0

Cześć Ahmed, spojrzałeś? – AndreaM16

Odpowiedz

1

końcu udało mi się rozwiązać ten problem.

Zasadniczo przyczyną problemu był schemat, ponieważ 2dIndex został skierowany do niewłaściwego pola (type and coordinates).

I rozwiązać za pomocą następującego schematu:

var mongoose = require('mongoose'); 
var GeoJSON = require('geojson'); 
var Schema = mongoose.Schema; 

var geoObjects = new Schema({ 
           name : {type: String}, 
           type: { 
             type: String, 
             enum: [ 
               "Point", 
               "LineString", 
               "Polygon" 
              ] 
             }, 
           coordinates: [Number], 
           created_at: {type: Date, default: Date.now}, 
           updated_at: {type: Date, default: Date.now} 
}); 

// Sets the created_at parameter equal to the current time 
geoObjects.pre('save', function(next){ 
    now = new Date(); 
    this.updated_at = now; 
    if(!this.created_at) { 
     this.created_at = now 
    } 
    next(); 
}); 

geoObjects.index({coordinates: '2dsphere'}); 

module.exports = mongoose.model('geoObjects', geoObjects); 

i następujący Query:

app.post('/query/', function(req, res) { 

     // Grab all of the query parameters from the body. 
     var lat = req.body.latitude; 
     var long = req.body.longitude; 
     var distance = req.body.distance; 

     var query = GeoObjects.find({'type':'Point'}); 

     // ...include filter by Max Distance 
     if (distance) { 

      // Using MongoDB's geospatial querying features. 
      query = query.where('coordinates').near({ 
       center: { 
        type: 'Point', 
        coordinates: [lat, long] 
       }, 

       // Converting meters to miles 
       maxDistance: distance * 1609.34, 
       spherical: true 
      }); 
     } 

     // Execute Query and Return the Query Results 
     query.exec(function(err, geoObjects) { 
      if (err) 
       res.send(err); 

      // If no errors, respond with a JSON 
      res.json(geoObjects); 
     }); 
    }); 

Mam nadzieję, że komuś pomóc!

EDIT

Schemat umieścić nad powoduje trochę problemów z LineStrings i Polygons.

Oto poprawne schematy, które pozwalają za pomocą geoQueries

LineString-model.js:

var mongoose = require('mongoose'); 
var Schema = mongoose.Schema; 

// Creates a LineString Schema. 
var linestrings = new Schema({ 
    name: {type: String, required : true}, 
    geo : { 
     type : {type: String, 
      default: "LineString"}, 
     coordinates : Array 
    }, 
    created_at: {type: Date, default: Date.now}, 
    updated_at: {type: Date, default: Date.now} 
}); 

// Sets the created_at parameter equal to the current time 
linestrings.pre('save', function(next){ 
    now = new Date(); 
    this.updated_at = now; 
    if(!this.created_at) { 
     this.created_at = now 
    } 
    next(); 
}); 

linestrings.index({geo : '2dsphere'}); 
module.exports = mongoose.model('linestrings', linestrings); 

wielokąta model.js

var mongoose = require('mongoose'); 
var Schema = mongoose.Schema; 

// Creates a Polygon Schema. 
var polygons = new Schema({ 
    name: {type: String, required : true}, 
    geo : { 
     type : {type: String, 
      default: "Polygon"}, 
     coordinates : Array 
    }, 
    created_at: {type: Date, default: Date.now}, 
    updated_at: {type: Date, default: Date.now} 
}); 

// Sets the created_at parameter equal to the current time 
polygons.pre('save', function(next){ 
    now = new Date(); 
    this.updated_at = now; 
    if(!this.created_at) { 
     this.created_at = now 
    } 
    next(); 
}); 

polygons.index({geo : '2dsphere'}); 
module.exports = mongoose.model('polygons', polygons); 

LineString Włóż:

{ 
    "name" : "myLinestring", 
    "geo" : { 
     "type" : "LineString", 
     "coordinates" : [ 
      [ 
       17.811, 
       12.634 
      ], 
      [ 
       12.039, 
       18.962 
      ], 
      [ 
       15.039, 
       18.962 
      ], 
      [ 
       29.039, 
       18.962 
      ] 
     ] 
    } 
} 

Polygon Wkładka:

{ 
    "name" : "Poly", 
    "geo" : { 
     "type" : "Polygon", 
     "coordinates" : [ 
          [ 
          [25.774, -80.190], [18.466, -66.118], 
          [32.321, -64.757], [25.774, -80.190] 
          ] 
         ] 
    } 
} 
5

Nie rozumiem co jest poniżej wszelkiej kodzie, ale wiem jedno:
Jeśli używasz Google Radar Search, trzeba wziąć pod uwagę, że

Maksymalny dozwolony promień wynosi 50 000 metrów.

Wystarczy spojrzeć na ich Documentation

To znaczy, że jeśli spróbujesz z większym promieniu, wyniki mogą być Zero

+1

Witam, bardzo doceniam twoją odpowiedź. Nie korzystam z wyszukiwarki radaru Google, próbuję korzystać z operatorów MongoDb w pobliżu i geoNear. Faktem jest, że, jak napisałem powyżej, kiedy miałem inny schemat Mongoose (tylko z markerami) moje zapytanie działało poprawnie. Parametr wyszukiwania MongoDB $ near i związane z nim właściwości maxDistance i sferyczny, aby określić zakres, który chcemy objąć. Mnożymy odległość naszego ciała zapytania przez 1609.34, ponieważ chcemy pobrać dane od naszych użytkowników (w milach) i przekonwertować je na jednostki, których MongoDB spodziewa się (w metrach). – AndreaM16

+1

Odnosząc się do linii 'console.log (users)', gdy napotkałem podobny problem. Problemem była nieblokująca natura JS, która szybciej wykonała log niż odpowiedź. W moim przypadku obietnica lub oddzwanianie rozwiązały problem. Czy próbowałeś tego rodzaju podejścia? –

+0

Tak, już próbowałem, ale zawsze jest niezdefiniowana. Myślę, że problem jest spowodowany moim nowym schematem i operatorem bliskim. – AndreaM16