Node.js 返回重复结果的Mongoose查询
查询接收一对坐标、最大距离半径、一个“跳过”整数和一个“限制”整数。函数应根据给定的位置返回最近和最新的位置。代码中没有可见的错误,但是,当我再次调用查询时,它会返回重复的结果。根据返回的结果更新“skip”变量 例如: 1) 我用skip=0,limit=10进行查询。我收到10个非重复位置 2) 现在再次调用Query,skip=10,limit=10。我从第一次查询中收到另外10个位置的重复结果 质疑 模式Node.js 返回重复结果的Mongoose查询,node.js,mongodb,mongoose,mongodb-query,aggregation-framework,Node.js,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,查询接收一对坐标、最大距离半径、一个“跳过”整数和一个“限制”整数。函数应根据给定的位置返回最近和最新的位置。代码中没有可见的错误,但是,当我再次调用查询时,它会返回重复的结果。根据返回的结果更新“skip”变量 例如: 1) 我用skip=0,limit=10进行查询。我收到10个非重复位置 2) 现在再次调用Query,skip=10,limit=10。我从第一次查询中收到另外10个位置的重复结果 质疑 模式 var locationSchema = new Schema({
var locationSchema = new Schema({
date_created: { type: Date },
coordinates: [],
text: { type: String }
});
我试着到处寻找解决办法。我唯一的选择是Mongo的版本?我使用Mongoose4.x.x,mongodb类似于2.5.6。我相信。有什么想法吗在你想要的结果中,有两件事情需要考虑,首先考虑的是,在“DATESORATION”中有一个“次要”的分类标准。 基本问题是,MongoDB中的运算符和类似运算符目前没有“投影”任何字段来指示与查询位置的“距离”,而只是对数据进行“默认排序”。所以为了进行“次要”排序,需要存在一个带有“距离”的字段。因此,这方面还有其他选择 第二种情况是,“跳过”和“限制”样式的分页对大数据集的表单性能非常糟糕,应该尽量避免。因此,最好根据数据出现的“范围”来选择数据,而不是“跳过”之前显示的所有结果 这里要做的第一件事是使用一个命令,该命令可以将距离与其他信息一起“投影”到文档中。的aggregation命令对此很有用,尤其是因为我们希望进行其他排序:
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
}
)
这是您的结果的第一次迭代,您将在其中获取前10个。注意循环中的逻辑,其中检查结果中的每个文档是否存在“date_created”或文档中当前存在的投影“dist”字段的更改,如果出现这种情况,“seenIds”数组将从所有当前条目中删除。一般的做法是在每次迭代中测试并可能更新所有变量,如果没有变化,则将项目添加到“seenid”列表中
所有这三个正在处理的变量都需要存储在某个地方,等待下一个请求。对于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
}
)
因此,输入“MindDistance”参数是为了排除已经看到的任何“更接近”的结果,并在查询中放置额外的检查,“date_created”需要“小于”记录的“lastDistance”,因为我们是按降序排序的,最后是“sure”筛选排除列表中记录的任何“_id”值,因为这些值没有更改
现在,对于地理空间数据,“seenIds”列表不太可能增长,因为通常情况下,您不会在相同的距离上找到所有东西,但这是一个分页排序数据列表的一般过程,因此值得理解这一概念
因此,如果您希望能够使用辅助字段对地理空间数据进行排序,并同时考虑“近”距离,那么这是一种通用方法,通过将距离值投影到文档结果中,以及在任何不会使其唯一的更改之前存储最后看到的值
一般的概念是“推进最小距离”,以使每页结果逐渐“远离”查询中使用的源起点。在执行
$near
后,您按创建的日期对结果进行排序,这不是一个好主意,也可能不是您想要的,因为它“扔掉了”由于近操作而返回的“排序”。在可能的情况下,也应避免使用“跳过”和“限制”分页方法,并且仅在“需要”编号分页以“跳转”到且没有其他方法的情况下使用。我认为它的目的至少是找到“最近的”东西,然后按照创造的顺序在大约相同的距离对任何东西进行排序?没错!我能做什么?传呼怎么样?你真的需要页码吗?或者你可以简单地要求下一页和下一页等等。这正是我的意思,获取一页,然后获取“下一页”等等,每次需要一个新页时,例如,你从不“跳到第5页”。我这样问是因为这避免了跳跃和限制,因此有更好的方法。
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
}
)