如何匹配MongoDB中给定的坐标列表中的任何位置?

时间:2012-08-20 11:40:02

标签: node.js mongodb mongoose geospatial

我目前正在使用带有node.js和Mongoose的MongoDB来执行地理空间搜索。

我正在使用以下文档和集合:

  • 航路点是包含位置和其他元数据的文档(就在那里,与此问题无关)
  • 目标集合包含1...n 航路点
  • 来源集合恰好包含1 航路点

这些文件的简单示例:

// Target
{
  waypoints: [
    {
      loc: [61.24, 22.24],
      time: 0
    },
    {
      loc: [61.25, 22.24],
      time: 1
    },
    {
      loc: [61.26, 22.24],
      time: 2
    },
  ]
}

// Source
{
  waypoint: {
    loc: [61.24, 22.24],
    time: 0
  }
}

所以我的问题是:

鉴于我们有一个特定的target文档(如上所述),找到所有source文档的最简单方法是(在MAX_DISTANCE距离内)任何给定的文档target

中的航点

匹配单个航点是微不足道的:

Source.find({
  'from.loc': {
    $within: {
      $center: [target.waypoints[0].loc, MAX_DISTANCE],
      $uniqueDocs: true
    }
  }
})

但是我很难找到如何匹配任何给定航点的解决方案。例如,以下查询不起作用:

Source.find({
  $or: [
    {
      'waypoint.loc': {
        $within: {
          $center: [target.waypoints[0].loc, MAX_DISTANCE],
          $uniqueDocs: true
        }
      }
    },
    {
      'waypoint.loc': {
        $within: {
          $center: [target.waypoints[1].loc, MAX_DISTANCE],
          $uniqueDocs: true
        }
      }
    },
    {
      'waypoint.loc': {
        $within: {
          $center: [target.waypoints[2].loc, MAX_DISTANCE],
          $uniqueDocs: true
        }
      }
    }
  ] 
})

任何想法为什么这不起作用,什么是替代?

非常感谢所有帮助!

P.S。我正在使用MongoDB v2.0.5,Mongoose 2.7.4&节点v0.8.7

1 个答案:

答案 0 :(得分:2)

无论如何,

$or查询在内部实现为单独的查询,因此除了缺乏优雅之外,类似以下内容的工作没有太多膨胀(在underscore库的帮助下) :

var nearSources = {}, count = target.waypoints.length;
target.waypoints.forEach(function (waypoint) {
  Source.find({
    'waypoint.loc': {
      $within: {
        $center: [waypoint.loc, MAX_DISTANCE],
        $uniqueDocs: true
      }
    }
  }, function (err, sources) {
    if (sources) {
      // Add the unique sources to the nearSources object by _id.
      sources.forEach(function (source) {
        nearSources[source._id] = source;
      });
    }
    if (--count === 0) {
      // Done!  Convert nearSources to an array of source docs.
      nearSources = _.values(nearSources);
    }
  });
});