2013-06-02 16 views
12

Ich frage mich, ob es möglich ist, eine Textsuche zu kombinieren und eine Geospatial-Abfrage auf die Ergebnisse auszuführen/wie ich es tun würde. Ich benutze Mongoose im Moment, aber nichts dagegen, gerade Mongo für die Befehle zu verwenden.MongoDB: Kombinieren von Textsuche und Geospatial Query

Ich versuche, den Benutzer zu ermöglichen, nach einem Produkt zu suchen und die Ergebnisse an einem bestimmten Ort zurückzugeben. Ich habe die zwei Befehle separat ausgeführt, kann aber nicht herausfinden, wie sie kombiniert werden.

Antwort

3

Sie können durch Hinzufügen eines Filterparameter einen Textsuche filtern (Ich verwende 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 ... 

    }); 

Wenn es eine grobe geographische Suche ist was Sie tun möchten, können Sie Ihre Ergebnisse filtern, indem ein bestimmendes min und max um den Breitengrad Längengrad:

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 

Hier ist etwas zu dem Thema in der mongodb Dokumentation ist: http://docs.mongodb.org/manual/tutorial/limit-number-of-items-scanned-for-text-search/

+1

kann ich $ lt und $ gt Betreiber verwenden, wenn die Breite und Länge in einem Array gespeichert werden ; etwas wie- loc: [50.433234,20,220123] –

4

Mongo DB selbst unterstützt keine Text- und Geo-Suche gleichzeitig. [Siehe this] (http://docs.mongodb.org/manual/reference/limits/#Queries-cannot-use-both-text-and-Geospatial-Indexes)

Sie es, indem Sie tun können

  1. Versuchen regex für Text und in der Nähe der Raumsuche.

    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. Verwendung Suche nach Textindex und die Verwendung folgenden Abfrage für nächste Dokumente, es ist nur gegenüber dem, was vorher gesagt.

    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. die Dokumente in mehrere Teile mit mapreduce aufgeteilt. Filtern Sie die Dokumente entweder nach Text/Geo-Suche und speichern Sie sie in einer neuen Sammlung. Gehen Sie durch die neue Sammlung und finden Sie die genaue Sammlung nach Filter. Diese

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

ist eine sehr häufige Anforderung in der geo-Filter und Textsuche in einem Anwendungsfall erforderlich ist, die leider direkt noch nicht von mongodb unterstützt.

Unten Code verwendet Mungo-Treiber, filtert Dokumente zuerst basierend auf Standort (Länge und Breite) und dann weitere Filter basierend auf dem gesuchten Begriff.

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 diesem Code "Post" ist ein Mungo-Schema wie etwas unter

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

Auch für den Suchbereich, gibt es andere wie Box verfügbaren Optionen

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

Sowohl für die Geolokalisierung Suche und Textsuche zu arbeiten, stellen Sie sicher, dass Index auf Loc-Feld und Textfeld. Weitere Details hier. loc Search

0

Volltextsuche ist mit Geospatial möglich.

können Sie versuchen, diese in Mongo Shell:

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

die Volltextsuche verwenden:

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