Найти все по расстоянию от контрольной точки - PullRequest
0 голосов
/ 07 мая 2011

В моем приложении Grails 1.3.7 у меня есть объект Building с двойной широтой и двойной долготой.Я реализую простую поисковую систему, чтобы найти все экземпляры Building с заданным расстоянием до точки, в которой находится пользователь (широта и долгота в десятичных градусах).Я нашел это http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL, что хорошо, потому что я использую базу данных MySQL.И аппроксимация ограничивающей рамки для меня превосходна, так как мне нужно выполнить дополнительную фильтрацию и вычисления, и мне просто нужен искатель, который сужает количество фильтруемых экземпляров.Мой вопрос: кто-нибудь уже реализовал этот вид поиска в среде Grails и как?

1 Ответ

1 голос
/ 08 мая 2011

Ранее я реализовал что-то с аналогичными требованиями и использовал HQL-запрос. Это было некоторое время назад, и я помню, что мне потребовалось много времени, чтобы прочитать и понять, так что, надеюсь, сэкономит вам время.

Это делает выбор на основе текущего местоположения (простой контейнерный объект длиной в длину) и «имени» (начинается с). Он выбирает объект домена (место проведения), а также мили вдали от текущего местоположения. Сортируется по милям по возрастанию. Примечание. Я добавил пометку «Дорожный фактор» для приблизительного расстояния до дороги.

def getVenuesInArea(venueName, location, miles, optionsMap)
{
    def max = optionsMap?.max ?: 10
    def offset = optionsMap?.offset ?: 0
    if (venueName == null) venueName = "" 
    venueName += '%'

    double roadFactor = 1.20 // add 20% for the roads, instead of as crow flies...

    def query
    def results

    def countQuery = """ select count( distinct v)

                from Venue as v
                WHERE
                v.name like :venueName AND
                ( acos
                    (
                        sin(radians(:lat))
                        * sin(radians(v.location.latitude))
                        + cos(radians(:lat))
                        * cos(radians(v.location.latitude))
                        * cos(radians(v.location.longitude) - radians(:lon))
                    ) * 3956.1676 * :roadFactor < :distance
                )

            """

    def count = Venue.executeQuery(countQuery, [venueName:venueName, lat:location.latitude, lon:location.longitude, distance:miles, roadFactor:roadFactor])[0]

    query = """ select distinct v,

                (
                    acos
                    (
                        sin(radians(:lat))
                        * sin(radians(v.location.latitude))
                        + cos(radians(:lat))
                        * cos(radians(v.location.latitude))
                        * cos(radians(v.location.longitude) - radians(:lon))
                    )
                    * 3956.1676 * :roadFactor
                ) as milesAway

                from Venue as v
                WHERE
                v.name like :venueName AND
                ( acos
                    (
                        sin(radians(:lat))
                        * sin(radians(v.location.latitude))
                        + cos(radians(:lat))
                        * cos(radians(v.location.latitude))
                        * cos(radians(v.location.longitude) - radians(:lon))
                    ) * 3956.1676 * :roadFactor < :distance
                )

                order by
                (
                    acos
                    (
                        sin(radians(:lat))
                        * sin(radians(v.location.latitude))
                        + cos(radians(:lat))
                        * cos(radians(v.location.latitude))
                        * cos(radians(v.location.longitude) - radians(:lon))
                    )
                    * 3956.1676 * :roadFactor
                )
                asc,
                v.name

            """

    results = Venue.executeQuery( query, [venueName:venueName, lat:location.latitude, lon:location.longitude, distance:miles, roadFactor:roadFactor, max:max, offset:offset])

    def venues = []
    MathContext mc = new MathContext(2)
    results.each
    { result ->
        VenueWithDetails venueDetails = new VenueWithDetails(  venue:result[0], milesFrom:new BigDecimal(result[1]).round(mc)  )
        venues.add(venueDetails)
    }
    return [venues:venues, count:count]
}

Это было сделано на Grails версии 1.3.4, но вполне уверен, что он должен хорошо работать на 1.3.7.

Надеюсь, это поможет, Крис.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...