Лучший способ дедупликации записей людей в Rails

Я пишу приложение rails с моделью Person, которая выглядит примерно так:

  create_table "people", :force => true do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.string   "email"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

У меня есть двухэтапный процесс следующим образом:

  1. Заполните записи о людях, указав имена людей. Имена людей могут иметь неизвестные дубликаты из-за псевдонимов и т. д. Например, «тим смит» и «тимоти смит».
  2. Запросите API, чтобы получить потенциальные совпадения адресов электронной почты для этих людей.

После выполнения этой обработки у меня могут быть такие данные, как:

запись 1: first_name: tim last_name: smith электронная почта: [email protected]

запись 2: first_name: timothy last_name: smith электронная почта: [email protected]

Каков наилучший способ в рельсах смоделировать, что это дубликаты?

ОБНОВЛЕНИЕ: РАЗЪЯСНЕНИЕ

После шага 2 я знаю, как узнать, что эти две записи являются дубликатами (то есть одним и тем же человеком), мой вопрос: как представить это в модели? Должен ли я добавить поле типа «duplicate_of_person_id» и поместить идентификатор первой записи в это поле во второй записи? Есть ли способ лучше?


person DougB    schedule 26.03.2013    source источник


Ответы (2)


Вы можете связать все записи вместе. Первая схема, которая приходит на ум, — оставить запись с наименьшим id победителем и сделать так, чтобы все дубликаты указывали на нее. Вы также можете сделать has_and_belongs_to_many, что потребует отдельной таблицы, где каждая запись говорит, что эти два человека одинаковы. Однако последний растет квадратично с количеством людей.

Или просто скопировать всю информацию из второго в первый и удалить второй.

person user3093911    schedule 12.12.2013

Не уверен на 100%, что вы просите. Если вы просто хотите найти дубликаты и, скажем, перечислить их в массиве, вы можете создать такой метод:

# This isn't particularly efficient, but it should return an array in which
# each element is a list of duplicated people (assuming we define duplicates
# by doubled email addresses). 
def self.find_duplicates
  array = []
  self.each do |person|
   similar = self.find_by_email
   if similar.count > 1
    array << similar
   end
  end
  return array
end

Если вы не хотите разрешать дубликаты, просто создайте проверку в своей модели:

validates :email, :uniqueness => true

не забудьте перед этим, однако, убедиться, что все электронные письма находятся в одном и том же регистре. Вы можете сделать что-то подобное, снова в модели:

before_validation :format_emails

def format_emails
  self.email = self.email.downcase
end
person Sasha    schedule 26.03.2013
comment
В базе данных следует выполнять проверки уникальности, чтобы избежать проблем с потоками и дрейфом, удалить сложный код для решения этих проблем и повысить эффективность. - person scones; 27.03.2013
comment
Threading: два экземпляра приложения одновременно отправляют одни и те же данные. Проверки приложений не смогут это уловить (я думаю, его также можно назвать race condition). Дрейфующие: настройка главного подчиненного сервера базы данных, при котором подчиненный сервер не получил новый набор данных, задается вопросом, существуют ли данные, и правдиво отвечает, что нет. тогда набор данных будет продублирован. - person scones; 27.03.2013
comment
Извините, должно было быть более ясно. После шага 2 я знаю, как узнать, что эти две записи являются дубликатами (то есть одним и тем же человеком), мой вопрос: как представить это в модели? Должен ли я добавить поле типа Duplicate_of_person_id и поместить идентификатор первой записи в это поле во второй записи? - person DougB; 27.03.2013