2013-06-02 10 views
12

Mi chiedevo se fosse possibile combinare una ricerca testuale ed eseguire una query geospaziale sui risultati/come lo farei. Al momento sto usando Mongoose, ma non mi dispiace usare Mongo dritto per i comandi.MongoDB: combina ricerca testo e query geospaziale

Quello che sto cercando di fare è consentire all'utente di cercare un prodotto e restituire i risultati che si trovano in una particolare posizione. Ho i due comandi in esecuzione separatamente, ma non riesco a capire come combinarli.

risposta

3

È possibile filtrare una ricerca di testo con l'aggiunta di un parametro di filtro (sto usando node-mongodb-native):

db.command({ text: 'thecollection', search: searchString, filter: query }, function(err, o) { 

    if (err) throw err; 

    var results = o.results.map(function(result) { return result.obj }); 

    // process the response ... 

    }); 

Se si tratta di un ruvido di ricerca geografica che si vuole fare, è possibile filtrare i risultati per la definizione di un min e max intorno alla vostra latitudine longitudine:

var distances = {'200m': 0.002, '500m': 0.005, '1km': 0.01, '5km': 0.05 } 

    , distance = distances[reqDis]; 


var query = { 
    latitude: { $lt: reqLat+distance, $gt: reqLat-distance }, 
    longitude: { $lt: reqLng+distance, $gt: reqLng-distance } 
}; 

// put the query in the db.command as described above 

Ecco qualcosa su questo argomento nella documentazione MongoDB: http://docs.mongodb.org/manual/tutorial/limit-number-of-items-scanned-for-text-search/

+1

posso usare $ operatori lt e $ GT se la latitudine e la longitudine sono memorizzati in un array ; qualcosa come- loc: [50.433234,20,220123] –

4

Mongo DB stesso non supporta testo e ricerca geografica contemporaneamente. [Suggerire questo] (http://docs.mongodb.org/manual/reference/limits/#Queries-cannot-use-both-text-and-Geospatial-Indexes)

si può fare seguendo

  1. Prova regex per il testo e vicino per la ricerca spaziale.

    var aggregate=YourCollection.aggregation() 
    aggregate.near({ 
        near:coord, 
        includeLocs: "loc", 
        distanceField: "distance", 
        maxDistance: distance 
    }); 
    aggregate.match({name:{$regex:keyword,$options: 'i'}}) 
    aggregate.exec(function(err,yourDocuments){ 
        //your smart code 
    }) 
    
  2. ricerca impiego per indice di testo e l'uso seguente query per i documenti più vicini, la sua proprio di fronte a quanto detto prima.

    var aggregate=YourCollection.aggregate(); 
    var match= { 
        latitude: { $lt: yourCurrentLatitude+maxDistance, $gt: yourCurrentLatitude-maxDistance }, 
        longitude: { $lt: yourCurrentLongitude+maxDistance, $gt: yourCurrentLongitude-maxDistance }, 
        {$text:{$search:keyword}} 
    }; 
    
    
    aggregate.match(match).exec(function(err,yourDocuments){//your smart code}) 
    

` 3. contempla i documenti in parti usando MapReduce. Filtrare i doucmets tramite testo/ricerca geografica e archiviarli in una nuova raccolta. Passa attraverso la nuova collezione e scopri la collezione esatta per filtro rimanente.

YourCollection.mapReduce(map, reduce, {out: {inline:1, query : yourFirstQuery}}, function(err, yourNewCollection) { 
    // Mapreduce returns the temporary collection with the results 
     collection.find(yourNewQuery, function(err, result) { 
      //your awsome code 
     }); 
    }); 
4

Questo è un requisito molto comune in cui è richiesto filtro geografico e ricerca di testo in un caso d'uso che purtroppo non direttamente supportato dal mongodb ancora.

Il codice riportato di seguito utilizza il driver mangusta, filtra i documenti per primi in base alla posizione (longitudine e latitudine) e quindi ulteriori filtri in base al termine cercato.

var area = { 
    center: [51, -114], //lng = 51 and lat = -114 
    radius: 100, 
    unique: true //this option is deprecated from MongoDB 2.6 on as mongodb no longer returns duplicate results 
}; 

var query = Post.where('loc').within().circle(area) //Step 1: filter based on location 
    //Step 2: Next filter on the basis of searched text 
    .where({ 
     $text: { 
      $search: <searchTerm> 
     } 
    }, { 
     score: { 
      $meta: 'textScore' 
     } 
    }) 
    //Step 3: Filter any document fields that should not be returned in the result 
    .select({ 
     "val1": 0, 
     "val2": 0 
    }); 

//Execute the query 
query.exec(function (err, result) { 
    if (err) { 
     //return error in the response 
    } 
    //return result object in the response 
}); 

In questo codice "Post" è un qualcosa di schema mangusta come qui di seguito

var PostSchema = new Schema({ 
    title: String, 
    description: String, 
    loc: { 
     type: [Number], // [<longitude>, <latitude>] 
     index: '2d' // create the geospatial index 
    } 
    //some other fields 
} 

module.exports = mongoose.model('Post', PostSchema); 

Anche per l'area di ricerca, ci sono altre opzioni disponibili come la scatola

var lowerLeft = [40.73083, -73.99756] 
var upperRight= [40.741404, -73.988135] 
query.where('loc').within().box(lowerLeft, upperRight) 

Per entrambi Geolocalizzazione ricerca e ricerca di testo per lavorare, assicurarsi di avere indice sul campo loc e sul campo di testo. Maggiori dettagli qui. loc Search e text search

0

La ricerca di testo completo è possibile con geospaziale.

Si può provare questo in guscio mongo:

db.collection.aggregate([ 
    { "$geoNear": { 
     "near": { 
      "type": "Point", 
      "coordinates": [ 
       -73.86, 
       41.076 
      ] 
     }, 
     "spherical": true, 
     "maxDistance": 600, 
     "distanceField": "distance", 
     "query": { 
      "fieldname": /querystring/ 
     } 
    }} 
]) 

Utilizzando la ricerca a testo integrale:

db.collection.find({ 
    "$text": { "$search": "query string" }, 
    "location": { // this will your field name 
     "$geoWithin": { 
      "$centerSphere": [[ 
       -73.86, 
       43.03 
      ], 500 ] 
     } 
    } 
})