2011-07-20 4 views
1

У меня есть приложение Rails 3, которое имеет модель с именем и географическим расположением (lat/lng). Как бы я мог найти возможные дубликаты в моей модели. Я хочу создать задание cron или что-то, что проверяет, есть ли у двух объектов одинаковое имя и что они находятся менее чем в 0,8 км друг от друга. Если это будет соответствовать, мы будем отмечать объекты или что-то еще.Обнаружение возможных дубликатов в рельсах

Я использую Ruby Geocoder и ThinkingSphinx в своем приложении.

+0

Что вы подразумеваете под похожим названием? Вы имеете в виду одно и то же имя? разные по случаям? или даже что-то вроде Vancouver & Vancuover – Olives

+0

[levenshtein] (http://raa.ruby-lang.org/project/levenshtein/) выглядит так, как мне кажется. –

+0

Возможно, вы могли бы подумать о том, как сделать это как подтверждение в своей модели вместо задания cron. – christianblais

ответ

1

Levenshtein - это такой же хороший способ, как и для оценки сходства двух текстовых строк, то есть имен.

То, что я хотел бы предложить, состоит в том, чтобы (а также, или вместо одиночной «длинной длинной» строки) хранить широту и долготу отдельно. Затем вы можете выполнить sql-запрос, чтобы найти другие записи, находящиеся на определенном расстоянии, затем запустите levenshtein на их имена. Вы хотите попытаться запустить lev как можно меньше, поскольку он медленный.

Тогда вы могли бы сделать что-то вроде этого: скажем, название модели является «место»:

class Place < ActiveRecord::Base 

    def nearby_places 
    range = 0.005; #adjust this to get the proximity you want 
    #lat and long are fields to hold the latitude and longitude as floats 
    Place.find(:all, :conditions => ["id <> ? and lat > ? and lat < ? and long > ? and long < ?", self.id, self.lat - range, self.lat + range, self.long - range, self.long + range]) 
    end 

    def similars 
    self.nearby_places.select do |place| 
     #levenshtein logic here - return true if self.name and place.name are similar according to your criteria 
    end 
    end 

end 

Я установил диапазон 0.005, но я понятия не имею, что это должно быть для 1/2 милю. Давайте рассмотрим это: google говорит, что одна градус широты составляет 69,13 миль, поэтому я думаю, что полмили в градусах будет 1/(69,13 * 2), что дает 0,0072, так что не плохое предположение :)

Обратите внимание, что мой логика поиска будет возвращать места, которые находятся где угодно в пределах квадрата, который составляет милю на каждую сторону, с нашим текущим местом в центре. Это потенциально может включать больше мест, чем круг с радиусом 1/2 мили с нашим текущим местом в центре, но, вероятно, это прекрасный способ получить некоторые близлежащие места.

Смежные вопросы