2016-06-09 9 views
12

Ho un problema che non sono riuscito a risolvere in alcuni giorni, anche analizzando Stack Overflow Q/UN.Individuazione dei punti più vicini a un determinato punto in base alle coordinate e alla distanza massima - Risultato della query non definito utilizzando Mangusta con stack MEAN

Sto sviluppando un'applicazione che riutilizza l'approccio Scotch's Create a MEAN Stack Google Map App Tutorial by Ahmed Haque.

Sto cercando di implementare un'applicazione che utilizza API di Google Maps disegnare Points, LineStrings e Polygons cui coordinate sono contenute nella GeoJSON file memorizzati in un MongoDB esempio.

Sto usando Mongoose per creare lo schema per i miei dati e interrogare il mio database MongoDB.

Mi piacerebbe trovare i punti più vicini CP ad un certo punti P0 dato P0's latitude and longitude e dato un raggio massimo distance utilizzato per trovare i punti interessati.

enter image description here

Data l'immagine sopra, vorrei che, per esempio, se inserisco 2000 (km), la mia domanda troverà tutti il ​​massimo dei punti distanti 2000 km P0. In questo esempio, probabilmente dovrebbe darmi P1 e P2.

Sono stato in grado di farlo quando avevo solo punti nel mio Mongoose Schema.

ho avuto questa Schema con solo i marcatori (punti):

// 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); 

E questo è stato il mio 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 
      }); 
     } 
}); 

ha funzionato molto bene, e sono stato in grado di ottenere punti vicini.

Quindi, ho cambiato il mio Schema per essere più dinamico e supporta anche Polylines and Polygons.

Sono in grado di inserire e disegnare nuovi punti, polilinee e poligoni con il seguente 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); 

E questo è il mio 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); mi dà undefined.

Risultati della query di registrazione nel mio queryCtrl.js mi dà il seguente messaggio di errore:

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"

Stessa cosa con una piccola variante:

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 
     }); 
    } 
}); 

Questo è un esempio di un marcatore:

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

    } 
} 

How $ near op erator lavora con la distanza e maxDistance:

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

parametro MongoDB ricerca $ vicino e le sue proprietà associate maxDistance e sferica per specificare l'intervallo che stiamo cercando di coprire. Stiamo moltiplicando la distanza del nostro corpo della query per 1609.34, perché vogliamo prendere l'input dei nostri utenti (in miglia) e convertirlo nelle unità previste da MongoDB (in metri).

  1. Perché mi undefined?
  2. È possibile che questo problema sia causato dal mio schema?
  3. Come posso risolvere questo problema?

Se desideri ricevere dei chiarimenti, inserisci un commento qui sotto.

Grazie in anticipo.

+1

Hey @ AndreaM16. Qualche possibilità che tu abbia questo codice su GitHub o qualcosa del genere in modo che possiamo abbassarlo e dare un'occhiata più da vicino? –

+0

Ciao Ahmed, hai dato un'occhiata? – AndreaM16

risposta

1

sono finalmente riuscito a risolvere questo problema.

In sostanza, il problema è stato causato dallo schema, dal momento che è stato riferito a un campo errato (type and coordinates).

ho risolto utilizzando il seguente schema :

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); 

E il seguente 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); 
     }); 
    }); 

spero che aiutare qualcuno!

EDIT

Lo schema ho messo sopra provoca un po 'di problemi con LineStrings e Polygons.

Qui ci sono schemi corretti che permettono di utilizzare geoQueries

stringa lineare-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); 

poligono-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 Inserire:

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

Poligono Inserire:

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

Non capisco che cosa c'è sotto tutto il codice, ma so una cosa:
Se si sta utilizzando di Google radar di ricerca, si deve prendere in considerazione il fatto che

Il raggio massimo consentito è di 50 000 metri.

Basta dare un'occhiata al loro Documentation

il che significa che se si tenta di raggio più alto, i risultati potrebbero essere Zero

+1

Ciao, apprezzo molto la tua risposta. Non sto utilizzando Ricerca radar di Google, sto cercando di utilizzare gli operatori di MongoDb vicino e geoNear. Il fatto è che, come ho scritto sopra, quando avevo uno schema Mongoose diverso (con solo marcatori) la mia query funzionava correttamente. Parametro di ricerca MongoDB $ vicino e le proprietà associate maxDistance e sferiche per specificare l'intervallo che intendiamo coprire. Stiamo moltiplicando la distanza del nostro corpo della query entro il 1609.34, perché vogliamo prendere l'input dei nostri utenti (in miglia) e convertirlo nelle unità che MongoDB si aspetta (in metri). – AndreaM16

+1

Per quanto riguarda la tua linea 'console.log (utenti)', una volta ho affrontato un problema simile. Il problema era la natura non bloccante di JS, che eseguiva più velocemente il log rispetto alla risposta. Nel mio caso, una promessa o una callback ha risolto il problema. Hai provato questo tipo di approccio? –

+0

Sì, l'ho già provato ma è sempre indefinito. Penso che il problema sia causato dal mio nuovo schema e dal vicino operatore. – AndreaM16

Problemi correlati