要检索的文档是具有一定范围(整数值)的导师,对应于他们将移动多远。 例如,如果客户在巴黎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楼 票数: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"]
            }
        }
    }
]);

  ask by Louis translate from so

未解决问题?本站智能推荐:

1回复

如何使用geoNear查询MongoDB?

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

MongoDB:并非使用$geoNear从查询返回所有结果

我收到了这个问题: 该查询应该在特定位置周围检索给定范围内的所有导师(这是来自导师模型的字段,以km为单位的整数,表示导师愿意移动多远)。 (lat1,lon1)。 问题是所有文件都没有退回。 经过多次测试后,我注意到只返回距离该位置不到7.5公里的导师,而不是其他导师。 即使导师
1回复

MongoDB的geoNear性能问题

嘿,我有一个MongoDB数据库,并且我在Mongoose中使用Node.js。 我有一个猫鼬模式看起来像这样的集合: 该馆藏很大(500'000个文档)。 当我执行一个简单的最近查找查询时,它运行速度非常快〜10 ms。 但是当我做这样的事情时: 这需要很长时间,大约60秒!
2回复

MongoDB:geoNear不返回距离

我需要修改现有的地理空间查询,以使其包含搜索结果中的距离。 (文档和现有查询都使用旧式坐标对。)原始查询使用$ near。 阅读MongoDB文档后,geoNear看起来应该返回距离,如几个示例所示。 虽然我已经可以修改查询以使用geoNear,但是距离不包括在搜索结果中。 这是新查询
1回复

GraphQL和MongoDB`$geoNear`聚合

我试图从我的MongoDB数据库中检索一些对象,这些对象的位置靠近给定的一组坐标,然后将它们排序为最接近最远的对象,这可以正常工作。 问题是我还想显示每个对象的距离,例如“ 1.3m远”。 我以前使用过$near ,它可以很好地工作,但改用$geoNear因为它可以通过向每个对象返回的js
1回复

使用MongoDB+Mongoose时无法解析$GeoNear索引

我花了一天的时间在mongo / mongoose文档中,并且在堆栈溢出时似乎无法弄清楚这一点。 这是我的基本架构设置: 我也尝试过: 我在createConnection上将autoIndex设置为false,因为Mongoose在应用程序启动时会自动调用createIndex ,
1回复

mongodb-当使用maxDistance时,使用$geoNear给出“geonear在查询GeoJSON点时只接受一个参数”

这似乎是一个常见的错误,但我似乎无法使其适用于我所看到的所有建议。 这是我的设置: 我得到这个错误: MongoError:无法确定查询系统是否可以提供覆盖投影 :: 由 :: geo near 在查询 GeoJSON 点时仅接受一个参数。 发现额外字段:$maxDistance:100000.
1回复

如何使用geoNear指定索引

我有一个包含两个2d索引的集合,我想对其中一个索引使用geoNear,但是我不知道如何指定它。 到目前为止,geoNear告诉我这一点:多个2d索引,不确定要在其上运行geoNear。 有什么办法吗?