猫鼬$ gte和$ lte无法正常工作

时间:2019-02-13 09:01:34

标签: node.js mongodb mongoose ecmascript-6

最近,我一直在开发一个应用程序,在该应用程序中,我需要获取位于特定位置半径范围内的文档。当我将纬度和经度发送到服务器时,我的代码会正确计算最小和最大纬度和经度。我尝试在猫鼬查询中将计算出的数字放入$ gte和$ lte内,但不会显示预期结果!

我尝试了以下猫鼬查询:

{ name: /^انار0$/i }

我得到了以下答复:

[
{
    "rating": {
        "average": 0,
        "count": 0
    },
    "location": {
        "latitude": 33.635,
        "longitude": 70.889
    },
    "status": "ONLINE",
    "_id": "5c62fa691fab8f24209f36e6",
    "name": "انار0",
    "_type": "CAFE"
}
]

但是当我发送位置并且查询变成以下内容时:

{ location:
    { latitude:
        { 
            '$gte': 33.626016646154675,
            '$lte': 33.64398335384532
         },
     longitude:
         { 
             '$gte': 70.88152061196703,
             '$lte': 70.89647938803296
          } 
      },
      name: /^انار0$/i
}

我得到一个空的jsonarray作为响应,响应与先前的查询应该没有不同!

这是我的代码:

let query = {};
if (location.lat && location.lng){
    /**
     * earth radius is approximately 6378 kilometers
     * so each degree is 111.3170 km based on the (2*Pi/360) * 6378
     * basically each degree is 111317 meters
     * if we want shops in a 1000 meter radius then 1000 meters in degree would be 1000 / 111317
     */
    let Pi = Math.PI;
    if (isNaN(radius)) {
        radius = 1000; // radius in meters
    }
    let radiusInDegrees = radius / 111317;

    let locationQuery = {};
    locationQuery.latitude = {};
    locationQuery.longitude = {};

    locationQuery.longitude.$gte = location.lng - (radiusInDegrees * Math.cos(location.lat * (Pi/180)));
    locationQuery.longitude.$lte = location.lng + (radiusInDegrees * Math.cos(location.lat * (Pi/180)));

    locationQuery.latitude.$gte = location.lat - radiusInDegrees;
    locationQuery.latitude.$lte = location.lat + radiusInDegrees;

    query.location = locationQuery;
}
if (s !== undefined){
    query.name = new RegExp(`^${s}$`, "i");
}
database.Shop.find(query)
    .sort(sort)
    .limit(per_page)
    .skip((page - 1) * per_page)
    .select("name logo status rating _type location")
    .populate("logo")
    .exec((err, shops) => {
        if (err){
            res.status(500);
            return res.json({
                status_code: 500,
                message: "internal server error"
            });
        }
        database.Shop.count(query, (err, count) => {
            res.header("document-count", count);
            let max_pages = Math.ceil(count / per_page);
            res.header("total-pages", max_pages);
            let fullUrl = req.protocol + '://' + req.get('host') + req.baseUrl;
            let originalQS = req.query;
            originalQS.page = page;
            originalQS.per_page = per_page;
            if (page < max_pages) {
                let qs = originalQS;
                qs.page = page + 1;
                res.header("next-page", fullUrl + "?" + queryString.stringify(qs));
            }
            if (page > 1 && max_pages > 0) {
                let previous_page = page - 1;
                if (page > max_pages) {
                    previous_page = max_pages;
                }
                let qs = originalQS;
                qs.page = previous_page;
                res.header("previous-page", fullUrl + "?" + queryString.stringify(qs));
            }
            res.header("page", page);
            res.json(shops);
        });
    });

1 个答案:

答案 0 :(得分:1)

您必须更新查询格式。对于嵌套对象,您需要使用点(.)表示法。因此请像"location.longitude"这样使用,而不要使用{ location:{ latitude:{....

因此您可以更新代码以构建类似于波纹管的查询

let query = {};
if (location.lat && location.lng) {
    let Pi = Math.PI;
    if (isNaN(radius)) {
        radius = 1000; // radius in meters
    }
    let radiusInDegrees = radius / 111317;


    query["location.longitude"] = {
        $gte: location.lng - (radiusInDegrees * Math.cos(location.lat * (Pi / 180))),
        $lte: location.lng + (radiusInDegrees * Math.cos(location.lat * (Pi / 180)))
    };

    query["location.latitude"] = {
        $gte: location.lat - radiusInDegrees,
        $lte: location.lat + radiusInDegrees
    };
}
if (s !== undefined) {
    query.name = new RegExp(`^${s}$`, "i");
}

这将生成类似波纹管的查询,并且应该可以正常工作

{
    'location.latitude': { '$gte': 33.626016646154675, '$lte': 33.64398335384532 },
    'location.longitude': { '$gte': 70.88152061196703, '$lte': 70.89647938803296 },
    name: /^انار0$/i
}