Avi*_*Avi 5 mongoose mongodb node.js mongodb-query aggregation-framework
该查询接收一对坐标、最大距离半径、“跳过”整数和“限制”整数。该函数应根据给定的位置返回最近和最新的位置。我的代码中没有明显的错误,但是,当我再次调用查询时,它会返回重复的结果。“skip”变量根据返回的结果进行更新。
例子:
1)我使用skip = 0,limit = 10进行查询。我收到10个非重复位置。
2) 现在再次调用查询,skip = 10,limit = 10。我收到另外 10 个位置,其中包含第一个查询的重复结果。
询问
Locations.find({ coordinates :
{ $near : [ x , y ],
$maxDistance: maxDistance }
})
.sort('date_created')
.skip(skip)
.limit(limit)
.exec(function(err, locations) {
console.log("[+]Found Locations");
callback(locations);
});
Run Code Online (Sandbox Code Playgroud)
模式
var locationSchema = new Schema({
date_created: { type: Date },
coordinates: [],
text: { type: String }
});
Run Code Online (Sandbox Code Playgroud)
我尝试到处寻找解决方案。我唯一的选择是 Mongo 版本?我使用 mongoose 4.xx,mongodb 就像 2.5.6。我相信。有任何想法吗?
在您想要的结果排序中,需要考虑几件事,首先要考虑的是您在“date_created”中需要处理“次要”排序标准。
基本问题是$nearMongoDB 中的运算符和类似运算符目前不会“投影”任何字段来指示距查询位置的“距离”,而只是对数据进行“默认排序”。因此,为了进行“辅助”排序,需要存在具有“距离”的字段。因此,还有其他选择。
第二种情况是“跳过”和“限制”样式的分页对于大量数据来说是可怕的表单性能,应该尽可能避免。因此,最好根据数据出现的“范围”来选择数据,而不是“跳过”之前显示的所有结果。
这里要做的第一件事是使用可以将距离与其他信息一起“投影”到文档中的命令。的聚合命令$geoNear对此很有用,特别是因为我们想要进行其他排序:
var seenIds = [],
lastDistance = null,
lastDate = null;
Locations.aggregate(
[
{ "$geoNear": {
"near": [x,y],
"maxDistance": maxDistance
"distanceField": "dist",
"limit": 10
}},
{ "$sort": { "dist": 1, "date_created": -1 }
],
function(err,results) {
results.forEach(function(result) {
if ( ( result.dist != lastDistance ) || ( result.date_created != lastDate ) ) {
seenIds = [];
lastDistance = result.dist;
lastDate = result.date_created;
}
seenIds.push(result._id);
});
// save those variables to session or other persistence
// do something with results
}
)
Run Code Online (Sandbox Code Playgroud)
这是结果的第一次迭代,您将在其中获取前 10 个结果。注意循环内部的逻辑,其中检查结果中的每个文档是否有“date_created”中的更改或现在存在于“date_created”中的投影“dist”字段的更改。文档,如果发生这种情况,“seenIds”数组将被擦除所有当前条目。一般操作是在每次迭代中测试并可能更新所有变量,如果没有更改,则将项目添加到“seenIds”列表中。
所有正在处理的这三个变量都需要存储在某个地方以等待下一个请求。对于 Web 应用程序来说,会话存储是理想的选择,但不同的方法有所不同。您只希望在我们开始下一个请求时调用这些值,因为在下一次和后续迭代中我们会稍微更改查询:
Locations.aggregate(
[
{ "$geoNear": {
"near": [x,y],
"maxDistance": maxDistance,
"minDistance": lastDistance,
"distanceField": "dist",
"limit": 10,
"query": {
"_id": { "$nin": seenIds },
"date_created": { "$lt": lastDate }
}
}},
{ "$sort": { "dist": 1, "date_created": -1 }
],
function(err,results) {
results.forEach(function(result) {
if ( ( result.dist != lastDistance ) || ( result.date_created != lastDate ) ) {
seenIds = [];
lastDistance = result.dist;
lastDate = result.date_created;
}
seenIds.push(result._id);
});
// save those variables to session or other persistence
// do something with results
}
)
Run Code Online (Sandbox Code Playgroud)
因此,当您想要排除任何已经看到的“较近”结果时,请输入“minDistance”参数,并且在查询中进行附加检查,其中“date_created”需要“小于”“由于我们按降序排序,因此也记录了“lastDistance”,最终的“sure”过滤器排除了列表中记录的任何“_id”值,因为这些值没有更改。
现在,对于地理空间数据,“seenIds”列表不太可能增长,因为通常您不会在相同的距离处找到所有内容,但这是对这样的数据排序列表进行分页的一般过程,因此值得理解这个概念。
因此,如果您希望能够使用辅助字段对地理空间数据进行排序,并考虑“近”距离,那么这是一般方法,将距离值投影到文档结果中并存储最后看到的值在任何不会使它们独一无二的更改之前。
一般概念是“推进最小距离”,使每页结果逐渐远离查询中使用的源点“更远”。
| 归档时间: |
|
| 查看次数: |
813 次 |
| 最近记录: |