【问题标题】:How to match any location from a given list of coordinates in MongoDB?如何匹配 MongoDB 中给定坐标列表中的任何位置?
【发布时间】:2012-08-23 09:00:10
【问题描述】:

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

我正在处理以下文档和集合:

  • waypoints 是包含位置和其他元数据的文档(只是存在,与此问题无关)
  • targets 集合包含 1...nwaypoints
  • sources 集合正好包含 1waypoint

这些文档的简单示例:

// 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 文档(如上面的那个),在@ 987654327@?

匹配单个航路点很简单:

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
        }
      }
    }
  ] 
})

任何想法为什么这不起作用以及有什么替代方法?

非常感谢所有帮助!

附:我正在使用 MongoDB v2.0.5、Mongoose 2.7.4 和节点 v0.8.7

【问题讨论】:

  • $any 不是顶级查询运算符。你正在寻找$或
  • 谢谢! $or 也不起作用 - 我将编辑问题以反映这一点。
  • 如果您发布示例数据和您正在尝试的 shell 兼容查询,我会尝试为您修复它。您的架构与您的查询不符(源中的“from”!=“waypoints”)
  • 当然,我会尝试这样做。请稍等!
  • 这也可能是相关的:jira.mongodb.org/browse/SERVER-3984

标签: node.js mongodb mongoose geospatial


【解决方案1】:

$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);
    }
  });
});

【讨论】:

  • 这不会给数据库带来非常高的负载吗?我的意思是,如果我有 1000 个航点怎么办?这基本上不会对数据库进行 1000 个并行查询吗?你知道有没有办法限制这个并行查询的数量?恐怕这是迄今为止最好的解决方案,但我很确定这不是唯一的答案!
  • 将会发生的事情是,Mongo 会将 Source 集合的 waypoint.loc 索引加载到内存中一次,然后将针对这 1000 个航点查询中的每一个进行查询。因此,虽然这听起来像是很多并行查询,但我希望它能够很好地执行,因为它几乎都是 CPU。不要过早地通过限制并行性来进行优化,因为这可能会浪费精力。
  • 感谢您的解释!我初步尝试了这个,它按预期工作 - 我只是担心这在性能方面是否是一个好主意。你绝对应该得到赏金。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-31
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2015-11-13
相关资源
最近更新 更多