最近,我一直在开发一个应用程序,在该应用程序中,我需要获取位于特定位置半径范围内的文档。当我将纬度和经度发送到服务器时,我的代码会正确计算最小和最大纬度和经度。我尝试在猫鼬查询中将计算出的数字放入$ 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);
});
});
答案 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
}