不能让我的地理空间查询工作.在Node中查询Mongo

Can't get my Geospatial Query to Work. Querying Mongo in Node

本文关键字:查询 工作 Mongo Node 空间 我的 不能      更新时间:2023-09-26

一旦用户登录他/或她的位置报告。并继续报告当前用户的位置每15分钟在那里。或者至少等到他们的疗程结束。使用Locate方法将用户位置读入数据库。它存储在与该特定用户关联的数据库中的位置数组中。这一切都很好。

将使用scan方法从数据库中读取用户位置。

我想知道如何创建一个2dsphere周围的位置坐标。我知道我得去目标地点。坐标,这样mongo就知道把它当作二维球体。我知道我必须使用User。ensureIndex({地点:" 2 dsphere "})。我的问题是:

1)应该是User.ensureIndex("location。坐标":2dsphere)或("location": 2dsphere)。这个会放在app.js.

的顶部吗?

2)在我的扫描方法中,我试图为具有匹配的用户名的文档创建逻辑和查询,除了在300米内。最后我的问题是我最后一个结构化正确的Mongo查询

我的mongo Schema是这样的:

var userSchema = mongoose.Schema({
  username: {
    type: String,
    required: true,
    unique: true
  },
  password: {
    type: String,
    required: true
  },
  email: {
    type: String
  },
  location: 
    {
      type: "Point",
      coordinates: [Number, Number],
      datetime: Date
  },
  points: {type:Number, default:10000},
  imageUrl: {type:String, default:'/img/gravatar.jpg'}
});

我的app.js是这样设置的:

var User = require('../models/users.js');

var userController = {
 locate: function (req, res) {
  var data = req.body;
  var date = new Date();
  var username = req.user.username;
  User.findOne({username:username}, function(err, user) {
    if (err) return handleErr(err);
    find = {
      coordinates: [data.longitude, data.latitude],
      datetime: date
    };
    user.location.push(find);
    user.save();
   });
 },
 scan: function (req, res) {
  var date = new Date();
  var twentyb4 = date.setMinutes(date.getMinutes - 15);
  User.find({"datetime": {$gte: twentyb4}}, function (err, user) {
    if (err) return handleErr(err);
    for (var i = 0; i < user.length; i++) {
    //return users other than current user
    if(req.user.username !== user[i].username){

       User.find({$and: [{username: user[i].username}, {$near:   {$geometry: {type: "Point", coordinates: [ req.user.longitude, req.user.latiude ]}, $maxDistance: 300, $minDistance: 0}}]}, function(err, data){
        if (err) return handleErr(err);

          console.log(data.username);
        });
      }

    }
  });      
};

所以scan函数最终要做的是找到数据库中不包括当前用户的所有用户。然后它只过滤那些在最近20分钟内登录过的用户。然后再进行一次筛选,比较其他用户最后报告的位置与当前用户的位置

你的模式是错误的,你需要修复这个:

  location: 
    {
      type: "Point",
      coordinates: [Number, Number],
      datetime: Date
  },

:

  location: {
      "type": { "type": String, "default": "Point" },
      "coordinates": [Number, Number],
      "datetime": Date
  },

由于"type"键工作被混淆,并且"Point"不是猫鼬数据类型。

您还需要为geoSpatial查询定义索引:

userSchema.index({ "location": "2dsphere" });

那么你的查询是相当简单的(你不需要$and在这里,因为所有的查询参数都是一个"answers"条件),你真的想要 $nearSphere 这里与现实世界的坐标:

User.find({ 
    "username": user[i].username,
    "$nearSphere": {
        "$geometry": {
            "type": "Point",
            "coordinates": [ parseFloat(req.user.longitude), parseFloat(req.user.latiude) ]
        }, 
        "$maxDistance": 300, 
        "$minDistance": 0
    }
}, function(err, data) {
});

也要注意parseFloat,因为我无法立即回忆起Mongoose是否真的有这样的$nearSphere查询的"类型转换"。

我还建议这里"不要循环",并且一次获取除当前用户名之外的所有用户。简单,有一些预过滤和 $in 运算符:

// Filter out username values only except for the current user
var otherUsers = user.map(function(u) {
    return u.username
}).filter(function(u) { return u != req.user.username });
if ( otherUsers.length > 0 ) {
    User.find({ 
        "username": { "$in": otherUsers },
        "$nearSphere": {
            "$geometry": {
            "type": "Point",
                "coordinates": [ parseFloat(req.user.longitude), parseFloat(req.user.latiude) ]
            }, 
            "$maxDistance": 300, 
            "$minDistance": 0
        }
    }, function(err, data) {
    });
} else {
   // no-one else is within the time :(
}

现在您在一个查询中测试了所有其他用户,因此您不需要为循环结果和相关的异步控制而烦恼,否则您也会真正需要这些。

您只需要创建一次索引(ensureIndex已弃用,createIndex中存在相同的功能)。由于您使用的是mongoose,所以只需在模式上定义索引,例如

userSchema.index({location: '2dsphere'});

你的查询差不多完成了,这是正确的版本。

var geoJSONpoint = {
   type: 'Point',
   coordinates: [
       req.user.longitude,
       req.user.latitude
   ]
}
User.find({ username: user[i].username, location: { $near: { $geometry: geoJSONpoint, $maxDistance: 300 } } })
...

下面是可行的解决方案:

我需要有:

var userSchema = mongoose.Schema({
  username: {
    type: String,
    required: true,
    unique: true
  },
  password: {
    type: String,
    required: true
  },
  location:
      {
        type: { type: String, default: "Point" },
        coordinates: [Number, Number],
        datetime: Date
      },
  email: {
    type: String
  }
})

userSchema.index({ "location.coordinates": "2dsphere"});  //In my model

这是我在Node (server)中的控制器:

scan: function (req, res) {
    var date = new Date();
    var minusmin = date.setMinutes(date.getMinutes() - 20);

    User.find({ "location.datetime": {$gte: minusmin}}, function (err, user) {
      if (err) return handleErr(err);

      for (var i = 0; i < user.length; i++) {
        //return users other than current user
        if(req.user.username !== user[i].username){

          User.find({ username: user[i].username, "location.coordinates": { $nearSphere: { $geometry: { type: "Point", coordinates: [ req.user.location.coordinates[0], req.user.location.coordinates[1] ]}, $maxDistance: 300 } } }, function(err, data){
              if (err) return handleErr(err);

              console.log(data);

          });

        }

      }
      res.send(user);
    });
  }