在mysql数据库中搜索 - 未序列化的数据

时间:2012-05-09 10:57:06

标签: mysql ruby-on-rails ruby serialization deserialization

情况: 我有用户模型。 db中的属性“meta_data”表示“text”类型字段。 在模型中,它按自定义类进行了序列化。 (serialize :meta_data, CustomJsonSerializer.new

这意味着,当我有一个用户实例时,我可以像使用Hash一样使用meta_data

User.first.meta_data['username']

问题:

我需要编写一个搜索功能,它将按给定的字符串搜索用户。我可以通过rails ex中的手动构建搜索查询来实现。 User.where("email LIKE '%#{string}%'")... 但是meta_data怎么样?我也应该通过LIKE语句搜索这个字段吗?如果我这样做,它将降低找到记录的相关性。

例如:

我有2个用户。其中一个有用户名“patrick”,另一个是“sergio”

db中的元数据将如下所示:

1){username:patrick}

2){username:sergio}

我想找塞尔吉奥,我输入一个搜索字符串“ser”=>但我有2个结果,而不是一个。这个meta_data字符串“{uSERname:Patrick}”也有“ser”,所以它使这个记录无关紧要。

你知道如何解决它吗?

1 个答案:

答案 0 :(得分:0)

这确实是序列化数据的问题。理论上,序列化可能是一种非常难以搜索的算法。它可以进行霍夫曼编码或其他压缩,并将序列化存储为二进制。您依赖于序列化使用JSON的假设,并且您的字符串仍然可以作为序列化中的子字符串找到。

那么你遇到的问题是另一个问题。序列化中的其他数据可能会弄乱您的结果。

通常,如果您序列化数据,则可以选择不可搜索。

因此,解决方案是添加一个以您控制的方式填充的其他字段。有一个值字段并存储可以搜索的管道(|)分隔值。因此,如果数据是{firstname:“Patrick”,姓氏:“Stern”},则您的meta_values字段可能是“Patrick | Stern”。

另外,不要将where方法与输入值扩展为#{}的字符串一起使用。这使它容易受到SQL攻击。而是使用:

where("meta_values is like :pattern", pattern: "%#{string}%")

我知道这可能看起来不太相似,但ActiveRecord会以这种方式进行消毒。如果有人在字符串中有一个分号,那么ActiveRecord将在搜索条件中转义分号。