Ситуация: У меня есть модель пользователя. атрибут "meta_data" в db представляет поле типа "текст". В модели она сериатизируется пользовательским классом. (serialize :meta_data, CustomJsonSerializer.new
)
Это означает, что когда у меня есть экземпляр пользователя, я могу работать с meta_data
как с Hash.
User.first.meta_data['username']
Проблема:
Мне нужно написать функцию поиска, которая будет искать пользователей по заданной строке. Я могу сделать это, выполнив поиск по поиску вручную в rails ex. User.where("email LIKE '%#{string}%'")...
Но как насчет meta_data? Должен ли я искать в этом поле также выражение LIKE? Если я это сделаю, это уменьшит релевантность найденной записи.
Например:
У меня 2 пользователя. У одного из них есть имя пользователя "patrick", другое - "sergio",
метаданные в db будут выглядеть так:
1) {имя пользователя: patrick}
2) {имя пользователя: sergio}
Я хочу найти sergio, я ввожу строку поиска "ser" =>, но у меня есть 2 результата, а не один. Эта строка meta_data "{uSERname: Patrick}" также имеет "ser", поэтому эта запись не имеет значения.
У вас есть идея, как его решить?
Это действительно проблема с сериализованными данными. Теоретически сериализация может быть алгоритмом, который является очень непостижимым. Он может кодировать Hoffman или другое сжатие и хранить сериализацию в двоичном формате. Вы полагаетесь на предположение, что сериализация использует JSON, и ваша строка будет по-прежнему отображаться как подстрока в сериализации.
Тогда проблема, с которой вы сталкиваетесь, - это еще одна проблема. Другие данные в сериализации могут испортить ваши результаты.
В общем, если вы сериализуете данные, вы делаете выбор, чтобы не быть доступным для поиска.
Таким образом, решение состоит в том, чтобы добавить дополнительное поле, которое вы заполняете таким образом, каким вы управляете. Имейте поле значений и сохраните значение, ограниченное каналом (|), которое вы можете искать. Поэтому, если данные являются {firstname: "Patrick", lastname: "Stern"}, поле meta_values может быть "Patrick | Stern".
Кроме того, не используйте метод where со строкой С# {} расширением входных значений. Это делает его уязвимым для SQL-атак. Вместо этого используйте:
where("meta_values is like :pattern", pattern: "%#{string}%")
Я знаю, что это может выглядеть не совсем по-другому, но ActiveRecord будет проходить санировку таким образом. Если у кого-то есть строка с двоеточием в строке, то ActiveRecord будет избегать полуколонии в условии поиска.