2013-06-02 12 views
12

Zastanawiałem się, czy można połączyć wyszukiwanie tekstowe i uruchomić kwerendę geoprzestrzenną na wynikach/jak to zrobić. Używam Mongoose w tej chwili, ale nie przeszkadza ci użycie prostego Mongo do poleceń.MongoDB: Łącz wyszukiwanie tekstu i zapytania geoprzestrzenne

Próbuję zezwolić użytkownikowi na wyszukanie produktu i zwrócenie wyników znajdujących się w określonej lokalizacji. Mam dwa polecenia uruchamiające się osobno, ale nie mogę wymyślić, jak je połączyć.

Odpowiedz

3

można filtrować wyszukiwanie tekstu przez dodanie parametru filtra (używam 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 ... 

    }); 

Jeśli jest szorstka wyszukiwania geograficzny chcesz zrobić, można filtrować wyniki od zdefiniowania min i max wokół swojej szerokości geograficznej:

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 

Oto coś na ten temat w dokumentacji MongoDB: http://docs.mongodb.org/manual/tutorial/limit-number-of-items-scanned-for-text-search/

+1

mogę użyć $ LT oraz $ gt operatorów, jeśli szerokość i długość geograficzna są przechowywane w tablicy ; coś w stylu - loc: [50.433234,20,220123] –

4

Sam Mongo DB nie obsługuje jednocześnie wyszukiwania tekstowego i geo. [zobacz ten] (http://docs.mongodb.org/manual/reference/limits/#Queries-cannot-use-both-text-and-Geospatial-Indexes)

Można to zrobić wykonując

  1. Spróbuj regex dla tekstu i blisko do wyszukiwania przestrzennego.

    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. użyć wyszukiwania indeksu tekstowego i użyć następującego zapytania do najbliższych dokumentów, jego przeciwieństwo do tego, co powiedzieliśmy wcześniej.

    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. Dzielenie się dokumenty w części z zastosowaniem MapReduce. Przefiltruj doucmety za pomocą wyszukiwania tekstowego/geo i zapisz je w nowej kolekcji. Przejdź przez nową kolekcję i znajdź dokładny zbiór przez filtr pozostałości.

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

Jest to bardzo częsty wymóg, gdy filtr geograficzny i wyszukiwanie tekstu jest wymagane w jednym przypadku użycia, który niestety nie jest jeszcze bezpośrednio obsługiwany przez mongodb.

Poniższy kod wykorzystuje sterownik mangusty, najpierw filtruje dokumenty na podstawie lokalizacji (długość i szerokość geograficzna), a następnie dodaje kolejne filtry w oparciu o wyszukiwany termin.

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

W tym kodzie „post” jest coś schematu mangusta jak poniżej

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

także dla obszaru wyszukiwania, istnieją inne opcje jak pudełka

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

Dla obu Geolokalizacja szukaj i szukaj tekstu do pracy, upewnij się, że masz indeks na pole i pole tekstowe. Więcej szczegółów tutaj. loc Search i text search

0

Wyszukiwanie pełnotekstowe jest możliwe dzięki geoprzestrzennemu.

Można spróbować tego w Mongo skorupy:

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

Używanie wyszukiwanie pełnotekstowe:

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