MongoDB:结合文本搜索和地理空间查询

Leo*_*das 13 mongoose mongodb

我想知道是否可以组合文本搜索并对结果/我将如何操作运行地理空间查询.我现在正在使用Mongoose,但不介意使用直接的Mongo来执行命令.

我要做的是允许用户搜索产品并返回特定位置内的结果.我有两个命令单独运行,但无法弄清楚如何组合它们.

b4d*_*d4r 6

Mongo DB 本身不同时支持文本和地理搜索。 参考这个

但是你可以结合查询并且可以达到结果

解决方案

  1. 正则表达式+附近
const 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
}) 
Run Code Online (Sandbox Code Playgroud)
  1. 文本搜索+ 正则表达式

    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})
    
    Run Code Online (Sandbox Code Playgroud)
  2. Mapreduce +(文本搜索正则表达式

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
    });
});
Run Code Online (Sandbox Code Playgroud)


Sau*_*hin 5

这是一个非常常见的需求,在一个用例中需要地理过滤器和文本搜索,不幸的是,mongodb 尚不直接支持。

下面的代码使用 mongoose 驱动程序,首先根据位置(经度和纬度)过滤文档,然后根据搜索词进一步过滤。

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
});
Run Code Online (Sandbox Code Playgroud)

在这段代码中,“Post”是一个猫鼬模式,如下所示

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);
Run Code Online (Sandbox Code Playgroud)

同样对于搜索区域,还有其他选项可用,例如框

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

要使地理位置搜索和文本搜索都能正常工作,请确保在 loc 字段和文本字段上有索引。更多细节在这里。loc 搜索文本搜索


kao*_*ore 3

您可以通过添加过滤器参数来过滤文本搜索(我使用的是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 ...

  });
Run Code Online (Sandbox Code Playgroud)

如果您想要进行粗略的地理搜索,您可以通过定义纬度经度周围的最小值和最大值来过滤结果:

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
Run Code Online (Sandbox Code Playgroud)

以下是 mongodb 文档中有关该主题的内容:http://docs.mongodb.org/manual/tutorial/limit-number-of-items-scanned-for-text-search/