MongoDB $geoWithin $centerSphere 查询

4

我在我的Node.js服务器中编写了以下模式:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var config = require('../../config.js');

var schema = new Schema({
        title   : { type: String, default: "generic"},
        guide   : String,
        loc     : {
            type : {type: String, default:"Point"},
            coordinates : [ ]
        },
    }
);
schema.index({"loc":"2dsphere"});
module.exports = mongoose.model(config.DATA_TYPE.SUPPORT, schema);

接下来我编写了用于添加、删除和查询的调度程序。添加和删除都没有问题,但是查询有些问题。

这是我的路由:

router.route('/')
    .post(function(req, res, next){
        SupportManager.getGuides(req.body.lat, req.body.lon, function(err,data){
            if(err){
                return res.json({
                        success: false,
                        message: 756
                });
            }else{
                return res.json({
                        success: true,
                        message: 856,
                        supports: data
                });
            }
        });
    })

我的SupportManager.getGuides代码如下:

getGuides: function(lat,lon,callback){
        Support.find({ loc: { $geoWithin: { $centerSphere: [[ lon , lat], 10/3963.2]}}}, callback);
    },

奇怪的现象是我在数据库中添加了以下对象:
{
    "_id": "58bf2f07d5fd2a0cdde4cca9",
    "guide": "a1",
    "loc": {
        "coordinates": [
            "34",
            "22"
        ],
        "type": "Point"
    },
    "title": "tappp",
    "__v": 0
}

但是当我使用lat=22和long=34进行研究时,我得到的答案是:

success: true,
message: 856,
supports: []

数组“supports”为空。


在您的centerSphere坐标中,顺序应为[lon,lat]。更多信息请参见https://docs.mongodb.com/manual/reference/operator/query/centerSphere/#op._S_centerSphere - s7vr
我修复了它,但还是不起作用... - pittuzzo
不是很确定。你也修好文档了吗? - s7vr
我清理了数据库并从零开始创建,还更改了架构并对齐了所有功能。我使用adminMongo看到问题应该在查询中。{ loc: { $geoWithin: { $centerSphere: [[ lon , lat], dist ]}}} - pittuzzo
你是否发现文档有什么问题? - pittuzzo
1个回答

2
代码很完美!只是坐标值未保存为数字。 因此,模式应该改为:
var schema = new Schema({
        title   : { type: String, default: "generic"},
        guide   : String,
        loc     : {
            type : {type: String, default:"Point"},
            coordinates : [ { Number } ]
        },
    }
);

数据库中的坐标数据现在将会是:

"loc": {
        "coordinates": [
            34,
            22
        ],
        "type": "Point"
    },

之前的值在 " " 之间:

"loc": {
        "coordinates": [
            "34",
            "22"
        ],
        "type": "Point"
    },

我建议您显式地将 then 转换为 Number 类型,而不是让模式处理它。显式类型转换可以帮助识别后期的错误,例如如果您稍后尝试对该值进行算术运算。比如说,如果您想将经度增加 5 度,那么 "32.4532"+5 将会被解析为 "32.45325",将数字连接到字符串的末尾,而不是将两个数字相加。明确确保您的类型可以是防止这些错误的好方法。 - tsturzl
将字符串转换为数字类型的简写方式是 var num = +str,在字符串前面使用 + 运算符,如果字符串不是数字,则返回 Nan。有关更多信息,请参见 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_plus_(.2B) 中的 "Unary Plus"。 - tsturzl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接