2016-06-04 10 views
1

Ich arbeite an einem Phoenix-Projekt, das lat/lng-Werte in MongoDB speichert und MongoDBs eingebaute Geo Abfragen verwenden muss, um Datensätze basierend auf der Entfernung zwischen zwei Punkten abzufragen.Ist es möglich Geospatial-Abfragen mit Ecto und MongoDB durchzuführen?

Ich habe mich den ganzen Morgen umgesehen, und habe this Geo repo gefunden, die auf Postgres ausgerichtet ist. Ich würde lieber nicht zu Postgres wechseln müssen, wenn es keine andere Möglichkeit gibt.

Hat jemand irgendwelche Erfahrungen mit Ecto/MongoDB und Geo Abfragen und kann mich in die richtige Richtung weisen, oder wissen, ob es momentan sogar mit Ecto möglich ist?

Eine mögliche Alternative könnte darin bestehen, einen einfachen Nodejs-Server mit Mungo einzurichten, um die Geo-Anfragen zu bearbeiten, und Phoenix dann bei Bedarf an diesen Dienst weiterleiten zu lassen? Aber ich würde natürlich eine Ecto-basierte Lösung bevorzugen, wenn eine verfügbar ist.

Dank

Paul

Antwort

1

Es ist nicht direkt in mongodb_ecto implementiert ist, aber Michał sagt es möglich, Fragmente verwenden sollte.

Im IRC, schrieb er:

etwas entlang der Linien von where: fragment(foo: ["$geoWithin": [...]])

$ geoWithin ausdrücklich von der ursprünglichen Arbeit ausgeschlossen ... https://github.com/michalmuskala/mongodb_ecto/issues/5

... und erscheint nicht im NormalizedQuery-Modul https://github.com/michalmuskala/mongodb_ecto/blob/master/lib/mongo_ecto/normalized_query.ex

Beachten Sie auch, dass mongodb_ecto immer noch Ecto 1.0 benötigt, Sie können es also nicht mit der Ecto 2 Beta verwenden.

1

Ja, das ist möglich. Sie können fragment wie bereits erwähnt verwenden. Ein vollständiges Beispiel könnte hilfreich sein:

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

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

Um diese Arbeit zu machen, werden Sie auch einen Index für das Standortfeld erstellen müssen. Gemäß der Dokumentation, ist der beste Weg GeoJSON zu verwenden, um die Position zu speichern, aber Sie können auch Arrays verwenden:

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

Dann können Sie erstellen Index mit 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