是否可以使用 Ecto 和 MongoDB 进行地理空间查询?

Is it possible to make Geospatial queries with Ecto and MongoDB?

我正在开发一个 Phoenix 项目,该项目将 lat/lng 值存储在 MongoDB 中,并且需要使用 MongoDB 的内置 Geo 查询才能根据两点之间的距离查询记录。

我整个上午都在四处寻找,找到了针对 Postgres 的 this Geo repo。我宁愿不必切换到 Postgres,除非没有其他选择。

有没有人有 Ecto/MongoDB 和 Geo 查询的经验,可以给我指明正确的方向,或者知道 Ecto 目前是否可行?

一种可能的替代方法是使用 mongoose 设置一个简单的 nodejs 服务器来处理地理查询,然后在必要时让 Phoenix 切换到该服务?但如果有的话,我显然更喜欢基于 Ecto 的解决方案。

谢谢

保罗

它没有直接在 mongodb_ecto 中实现,但 Michał 说应该可以使用片段。

在 IRC 中,他写道:

something along the lines of where: fragment(foo: ["$geoWithin": [...]])

$geoWithin 被明确排除在原始作品之外... https://github.com/michalmuskala/mongodb_ecto/issues/5

...并且没有出现在 NormalizedQuery 模块中 https://github.com/michalmuskala/mongodb_ecto/blob/master/lib/mongo_ecto/normalized_query.ex

另请注意,mongodb_ecto 仍需要 Ecto 1.0,因此您不能将其与 Ecto 2 beta 一起使用。

是的,这是可能的。您可以如前所述使用 fragment 。一个完整的例子可能会有帮助:

near_sphere = [
  "$nearSphere": [
    "$geometry": [
      "type": "Point",
      "coordinates": [10.0, 20.0]
    ],
    "$maxDistance": 1000
  ]
]

from(c in City, where: fragment(location: ^near_sphere)

为了完成这项工作,您还需要为位置字段创建索引。根据文档,最好的方法是使用 GeoJSON 来存储位置,但您也可以使用 array:

defmodule MyApp.City do
  # ...
  schema "cities" do
    field :location, {:array, :float}
  end
end

然后你可以创建索引 execute/1 (https://hexdocs.pm/ecto/Ecto.Migration.html#execute/1)

def up do
  execute [
    createIndexes: "cities",
    indexes: [
      [
        key: [location: "2dsphere"],
        name: "location_2dsphere",
        "2dsphereIndexVersion": 3
      ]
    ]
  ]
end

def down do
  execute [
    dropIndexes: "cities",
    index: "location_2dsphere"
  ]
end