繁体   English   中英

MongoDB,如何使用$ geoNear检索给定范围内的文档

MongoDB, how to retrieve documents in a given range with $geoNear

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

要检索的文档是具有一定范围(整数值)的导师,对应于他们将移动多远。 例如,如果客户在巴黎48街de Varenne找一位导师,我们应该只检索可以去巴黎48 rue de Varenne 的导师搜索位置和导师位置之间的距离必须小于导师范围

你知道怎么做吗? 查询是纬度和经度(位置),导师还具有位置(纬度和经度)和范围(他能走多远)。

这是导师模型的简化版本:

import mongoose from 'mongoose';
import validate from 'mongoose-validator';
import { User } from './user';
import mongooseAggregatePaginate from 'mongoose-aggregate-paginate';

var ObjectId = mongoose.Schema.Types.ObjectId;


var tutorSchema = mongoose.Schema({
    location: {
        address_components: [
            {
                long_name: String,
                short_name: String,
                types: String
            }
        ],
        description: String,
        lat: Number,
        lng: Number

    },
    range: {
        type: Number,
        default: 15
    },
    loc: {
        type: { type: String },
        coordinates: []
    }
});

tutorSchema.plugin(mongooseAggregatePaginate);
tutorSchema.index({ "loc": "2dsphere" });
module.exports = {
    Tutor
};

这是我到目前为止的查询(不考虑范围, lon1和lat1是查询参数 ):

 exports.search = (req, res) => {
  let lat1 = req.body.lat;
  let lon1 = req.body.lng;
  let page = req.body.page || 1;
  let perPage = req.body.perPage || 10;
  let radius = req.body.radius || 10000;

  let levelsIn = req.body.levels && req.body.levels.length !== 0 ? req.body.levels.map(level => {
    return ObjectID(level);
  }) : null;
  let subjectsIn = req.body.subjects && req.body.subjects.length !== 0 ? req.body.subjects.map(subject => {
    return ObjectID(subject);
  }) : null;

  var options = { page: page, limit: perPage,  sortBy: { updatedDate: -1 } }

  const isAdmin = req.user ? req.user.role === "admin" || req.user.role === "super-admin" : false;

  let match = {}

  if (levelsIn) match.levels = { $in: levelsIn };
  if (subjectsIn) match.subjects = { $in: subjectsIn }
  if (typeof req.body.activated !== "undefined") match.profileActivated = req.body.activated;
  if (req.body.from) match.createdAt = { $gte: new Date(req.body.from) };
  if (req.body.to) {
    if (match.createdAt) match.createdAt.$lte = new Date(req.body.to);
    else match.createdAt = { $lte: new Date(req.body.to) };
  }

  var aggregate = null;

  if (!isAdmin) {
    match.activated = true
    match.profileActivated = true
    match.profileOnline = true
  }

  if (lat1 && lon1) {

   match.$expr = {
        $lt: ["$distance", "$range"] // "calculated_distance < tutor_range"
     }

       aggregate = Tutor.aggregate([
     {

       "$geoNear": {
         "near": {
           "type": "Point",
           "coordinates": [lon1, lat1]
         },
         "distanceField": "distance", // this calculated distance will be compared in next section
         "distanceMultiplier": 0.001,
         "spherical": true
       }
     },
     {
       $match: match
     }
     ]);
  } else {
    aggregate = Tutor.aggregate([
      {
        $match: match
      }
    ]);
  }

  Tutor
    .aggregatePaginate(aggregate, options, function (err, result, pageCount, count) {
      if (err) {
        return res.status(400).send(err);
      }
      else {

        var opts = [
          { path: 'levels', select: 'name' },
          { path: 'subjects', select: 'name' },
          { path: 'assos', select: 'name' }
        ];
        Tutor
          .populate(result, opts)
          .then(result2 => {
            return res.send({
              page: page,
              perPage: perPage,
              pageCount: pageCount,
              documentCount: count,
              tutors: result2
            });
          })
          .catch(err => {
            return res.status(400).send(err);
          });
      }
    })
};

谢谢您的帮助 !

1 个回复

您只需要在管道中添加一个过滤器来比较distancerange字段:

{
    $match: {
        $expr: {
            $lt: ["$distance", "$range"] // "calculated_distance < tutor_range"
        }
    }
}

完整查询:

aggregate = Tutor.aggregate([{
        "$geoNear": {
            "near": {
                "type": "Point",
                "coordinates": [lon1, lat1]
            },
            "distanceField": "distance", // this calculated distance will be compared in next section
            "spherical": true
        }
    },
    {
        $match: {
            $expr: {
                $lt: ["$distance", "$range"]
            }
        }
    }
]);
3 获取日期范围内给定时间范围的Mongodb文档

我想找出在给定日期范围内某个时间段之间存在的文档。 我只有一个字段“ date”,它存储为Date对象。 例如 - 查找日期为2018年1月10日至2018年1月30日的所有文档,其时间为上午10:00至晚上23:30 (另外我目前正在使用3.4版) ...

2018-08-01 05:54:08 3 111   mongodb
4 如何使用geoNear查询MongoDB?

我正在尝试使用mongodb使用聚合函数geoNear和near来定位距离,具体取决于经度和纬度。 我收到一条错误消息: MongoError:当查询GeoJSON点时,geo near仅接受一个参数。 找到的额外字段:$ max距离:100000.0 ...

6 使用GeoNear返回MongoDB中按字段分组的最近文档

我正在使用官方的C#驱动程序通过GeoNear在MongoDB中查询集合。 这些文件看起来像这样: 在多对多方案中,资源和站点有多种组合。 我的geoNear工作正常,但现在需要根据其他条件过滤结果。 我具有基础知识,因此例如可以返回所有特定资源类型,但是现在我需要查询 ...

8 Mongodb 查询:查找在给定范围内具有数组所有元素的文档

假设我有一个集合,其文档具有这种结构 其中ts是一个包含两个Long元素的数组,其中第二个元素严格大于第一个元素。 我想检索数组ts所有元素都在一个范围内(大于一个值但小于另一个值)的所有文档。 假设范围在4到9之间; 我正在尝试这个查询,但我发现了意想不到的结果: ...

9 MongoDB在给定的时间范围内迭代

我能够设置以下脚本,该脚本显示用户最近一次登录时最接近给定日期及其电池电量的脚本。 现在,我想在给定的时间范围内将其封装起来,比如说2013-09-17T13:25:56.314Z至2013-09-17T23:25:56.314Z我将如何去做,并在循环中每次迭代五次分钟? 我也想将信息 ...

10 检索Linq给定范围内的特定星期几?

是否可以给出一个日期范围来抽出一周中的特定日期并显示其日期? 所以,如果我的日期范围是从2012年8月17日到2012年9月17日,那么有可能使用linq来说出所有周四和周二吗? ...

2012-07-24 13:56:01 2 2528   c#
暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM