【问题标题】:MongoDB: Combine Text Search and Geospatial QueryMongoDB:结合文本搜索和地理空间查询
【发布时间】:2020-11-27 22:53:55
【问题描述】:

我想知道是否可以结合文本搜索并对结果运行地理空间查询/我将如何做到这一点。我目前正在使用 Mongoose,但不介意直接使用 Mongo 作为命令。

我想要做的是允许用户搜索产品并返回特定位置内的结果。我有两个命令分别运行,但不知道如何组合它们。

【问题讨论】:

    标签: mongodb mongoose


    【解决方案1】:

    Mongo DB 本身不支持文本和地理搜索。 Refer this

    但是可以结合查询,可以达到结果

    解决方案

    1. regex + near
    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
    }) 
    
    1. Text search + regex

      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})
      
    2. Mapreduce + (Text searchregex)

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

    【讨论】:

      【解决方案2】:

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

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

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

      在这段代码中,“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);
      

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

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

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

      【讨论】:

        【解决方案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 ...
        
          });
        

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

        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
        

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

        【讨论】:

        • 如果将纬度和经度存储在数组中,我可以使用$lt和$gt运算符吗?类似 loc:[50.433234,20,220123]
        【解决方案4】:

        使用地理空间可以进行全文搜索。

        你可以在 mongo shell 中试试这个:

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

        使用全文搜索:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-10-31
          • 1970-01-01
          • 2015-06-07
          • 1970-01-01
          • 1970-01-01
          • 2019-09-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多