0

情况:我有用户模型。db 中的属性“meta_data”表示“文本”类型字段。在模型中,它由自定义类序列化。( 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){用户名:帕特里克}

2){用户名:塞尔吉奥}

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

你知道如何解决它吗?

4

1 回答 1

0

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

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

一般来说,如果您对数据进行序列化,您就是在选择不可搜索。

因此,一种解决方案是添加一个您以您控制的方式填充的附加字段。有一个值字段并存储您可以搜索的竖线 (|) 分隔值。因此,如果数据是 {firstname: "Patrick", lastname: "Stern"},您的 meta_values 字段可能是“Patrick|Stern”。

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

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

我知道这看起来可能没什么不同,但 ActiveRecord 会以这种方式进行清理。如果有人在字符串中有分号,那么 ActiveRecord 将在搜索条件中转义分号。

于 2012-05-09T11:10:45.377 回答