2016-07-29 80 views
1

我想这样做:

model.User.aggregate([ 
    //step 1 match criteria 
    { 
     $match: criteria 
    }, 
    //step 2 skip 
    { 
     $skip: offset 
    }, 
    //step 3 limit 
    { 
     $limit: limit 
    }, 
    //step 4 sort by computed distance 
    { 
     $geoNear : { 
      near: {type: 'Point', coordinates: coords }, 
      distanceField: 'currentCity.computed_distance', 
      includeLocs: 'currentCity.loc', 
      spherical: true, 
      uniqueDocs: true, 
      distanceMultiplier: 3963.2, //convert to miles (this number is the radius of the earth in miles) 
     } 
    } 
],function(err,users){ 
    if (err) return res.error(err); 
    if (!users.length) return res.error('no matched criteria'); 
    res.apiResponse(users); 
}); 

$ geoNear的文档状态:

您只能使用$ geoNear作为管道的第一阶段。

阅读该文档,我知道我可以在里面$geoNear通过query选项只需移动$match。同样,$limit可能通过limit选项放置在$geoNear的内部。一个问题是,$skip选项没有等效,所以看起来好像无法实现分页功能?我真的很困惑,为什么$geoNear不能成为第四步。查询的目的是简单地找到最好的n匹配,其中n = limit,然后按距离最近排序。这甚至有可能吗?我无法找到这个特定用例的答案。

我想一个解决方案可能是有$in查询像这样执行查询只选择IDS匹配的文档,转换为ID的列表,然后做骨料:

model.User.find(criteria).skip(offset).limit(limit).select('_id').exec(function (err, userIds) { 
    var ids = []; 
    userIds.forEach(function(u){ 
     ids.push(u._id); 
    }); 

    model.User.aggregate([ 
     { 
      $geoNear : { 
       query: { _id: {$in: $ids } }, 
       near: {type: 'Point', coordinates: coords }, 
       distanceField: 'currentCity.computed_distance', 
       includeLocs: 'currentCity.loc', 
       spherical: true, 
       uniqueDocs: true, 
       distanceMultiplier: 3963.2, //convert to miles (this number is the radius of the earth in miles) 
      } 
     } 
    ],function(err,users){ 
     if (err) return res.error(err); 
     if (!users.length) return res.error('no matched criteria'); 
     res.apiResponse(users); 
    }); 
}); 

这会工作,但理想情况下,如果可能,我可以在1个查询中完成。任何想法非常赞赏。

回答

0

一种解决方案是这一个:

result = db.cafes.aggregate([{ 
'$geoNear': { 
    'near': { 
     'type': 'Point', 
     'coordinates': [ 
      -73.991084, 
      40.735863]}, 
    'spherical': True, 
    'distanceField': 'dist', 
    'num': 20} 
}, { 
    '$skip': 10 
}]) 

还有这种方法更好的解决方案:

ids = [42] 

result = db.command(
'geoNear', 'cafes', 
near={ 
    'type': 'Point', 
    'coordinates': [ 
     -73.991084, 
     40.735863]}, 
spherical=True, 
minDistance=268, 
query={ 
    '_id': { 
     '$nin': ids}}, 
num=10) 

而且一个非常好的解释速度和问题在这里:

https://emptysqua.re/blog/paging-geo-mongodb/