0

状況: ユーザー モデルがあります。db の属性「meta_data」は、「テキスト」タイプのフィールドを表します。モデルでは、カスタム クラスによってシリアライズされます。( serialize :meta_data, CustomJsonSerializer.new)

つまり、user のインスタンスがあれば、meta_dataHash と同じように操作できます。

User.first.meta_data['username']

問題:

指定された文字列でユーザーを検索する検索関数を作成する必要があります。Rails exで検索クエリを手動で構築することで実行できます。User.where("email LIKE '%#{string}%'")... しかし、 meta_data はどうですか? このフィールドも LIKE ステートメントで検索する必要がありますか? もしそうすると、見つかったレコードの関連性が低下します。

例えば:

2 人のユーザーがいます。そのうちの 1 つはユーザー名が「patrick」で、もう 1 つは「sergio」です。

db のメタデータは次のようになります。

1) {ユーザー名: パトリック}

2) {ユーザー名: セルジオ}

sergio を見つけたいのですが、検索文字列「ser」を入力します => しかし、1 つではなく 2 つの結果が得られます。このメタデータ文字列「{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 に答える