MongoDB:考虑到多个字段,我如何按距离订购?

时间:2014-07-10 08:58:10

标签: mongodb mongodb-query geospatial

我有一个存储医生信息的集合。每位医生都可以在私人诊所和/或医院工作。 该集合具有以下相关字段(privatePractices.address.loc和hospitals.address.loc上都有地理空间索引):

{
  "name" : "myName",
  "privatePractices" : [{
      "_id": 1,
      "address" : {
        "loc" : {
          "lng" : 2.1608502864837646,
          "lat" : 41.3943977355957
        }
      }
    },
    ...
    ],
  "hospitals" : [{
      "_id": 5,
      "address" : {
        "loc" : {
          "lng" : 2.8192520141601562,
          "lat" : 41.97784423828125
        }
      }
    },
    ...
    ]
}

我正在尝试查询该集合,以获取按给定点距离排序的医生列表。这就是我陷入困境的地方:

以下查询返回按距离排序到$ nearSphere中定义的点的医生列表,仅考虑两种位置类型中的一种:

{ "hospitals.address.loc" : { "$nearSphere" : [2.1933, 41.4008] } }
{ "privatePractices.address.loc" : { "$nearSphere" : [2.1933, 41.4008] } }

我想要的是让最近的医院或私人诊所命令医生,无论最近的是什么。是否可以在单个Mongo查询中执行此操作?

计划B是使用上面的查询,然后在Mongo外部手动排序结果(例如使用Linq)。要做到这一点,我的两个查询应该返回每个医院或私人诊所到$ nearSphere点的距离。是否有可能在Mongo中这样做?

编辑 - 应用解决方案(MongoDB 2.6): 我采用了自己的方法,灵感来自Neil Lunn在答案中的建议:我在Doctor文档中添加了一个用于分类目的的字段,其中包含一个包含医生所有位置的数组。

我在MongoDB 2.4和MongoDB 2.6中尝试过这种方法,结果不同。 2.4上的查询返回了具有多个位置的重复医生,即使_id包含在查询过滤器中也是如此。 2.6上的查询返回有效结果。

1 个答案:

答案 0 :(得分:3)

我本来希望在这里获得更多信息,但基本知识仍然适用。因此,您偶然发现的一般问题是尝试将“两个”位置字段显示在您的医生文档上。

该方法还有另一个问题。您在文档中的数组中有“位置”/这在创建索引时不会给您带来错误,但它也不会像您期望的那样工作。这里的一个大问题是,在数组中,您可能会发现“包含”最近位置的文档,但问题是“哪一个”,因为没有做任何事情来影响数组内容。

核心问题是,每个查询不能有多个地理空间索引。但要真正得到你想要的东西,把问题转向它的头部,基本上把医生连接到位置,这是另一种方式。

例如,这里是一个“实践”集合或等等:

{
    "type": "Hospital",
    "address" : {
        "loc" : {
          "lng" : 2.8192520141601562,
          "lat" : 41.97784423828125
        }
    },
    "doctors": [
        { "_id": 1, "name": "doc1", "specialty": "bones" },
        { "_id": 2, "name": "doc2", "specialty": "heart" }       
    ]
}

{
    "type": "Private",
    "address" : {
       "loc" : {
          "lng" : 2.1608502864837646,
          "lat" : 41.3943977355957
       }
    },
    "doctors": [
        { "_id": 1, "name": "doc1", "specialty": "bones" },
        { "_id": 3, "name": "doc3", "specialty": "brain" }
    ]
}

这里的优点是你在这里作为一个集合并且在同一个索引中你可以简单地获得两个“类型”并按距离或在界限内或者你的地理查询需要的任何地方正确排序。这避免了其他建模形式的问题。

至于“医生”信息,当然你实际上是为自己的医生信息保留了一个单独的集合,甚至可能还为那里的位置文件保留了一组_id值。但这里的要点是,您通常可以将一些有用的搜索信息“嵌入”在这里的一些有用的搜索信息中来帮助您。

这似乎是更好的选择,并且将医生与位置内的标准相匹配是可以完成的事情,其中​​查找或排序数组内最近的条目是MongoDB不支持的内容本身,并将导致您自己应用数学处理结果。