一般的にWebサービスの検索フォームだと
A B C
と入力するとAが含まれていてかつBが含まれていてかつCが含まれているものが抽出されますが、
某Webサービスの場合だと
A (B OR C)
等を入力すると論理式通りAが含まれているかつBかCが含まれているものが抽出されます。
この処理って内部的には論理式をSQLのWHERE句に変換してるものだと思うのですが、
どういうロジックになってるのでしょうか・・・?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
電卓を作るようなロジックで動的に作ってるか
事前に考えられるパターンを網羅しているのではと思います。
投稿2016/10/18 20:56
退会済みユーザー
総合スコア0
0
この処理って内部的には論理式をSQLのWHERE句に変換してるものだと思うのですが、
どういうロジックになってるのでしょうか・・・?
やり方はいくらでもあると思いますが、あんまり何も考えないで簡単に書くと
ruby
1def to_query(string) 2 string.gsub(' ', ' AND ').gsub(/ AND (AND|OR) AND /, ' \1 ') 3end
とかでも一応できますね。
ruby
1to_query('A B C') # => "A AND B AND C" 2to_query('A (B OR C)') # => "A AND (B OR C)" 3to_query('A OR B OR C') # => "A OR B OR C" 4to_query('A OR B AND C') # => "A OR B AND C" 5to_query('A OR B C') # => "A OR B AND C" 6to_query('(A OR B) C') # => "(A OR B) AND C" 7to_query('(A OR B) AND C') # => "(A OR B) AND C" 8to_query('(A OR B) AND C (D OR Z) (Z X)') # => "(A OR B) AND C AND (D OR Z) AND (Z AND X)"
投稿2016/10/16 23:57
総合スコア1728
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
自分ならフォームの値を、パースしてから、Where句を組み立て直しますかね。
※Where句にそのまま使ったらSQLインジェクションの可能性があるので、絶対にしません。
パースでは、スペースやカッコで文字列分割して、カッコ内のものは、配列的にもネスト構造にしておきます。
次にWhere句を組み立てで、文字列が特殊なキーワード(OR AND NOTなど)があれば、それに準じてSQLを作る感じでしょうか。
フレームワークなどでは、配列形式の条件からWhere句を作ってくれるものがあるので、それを利用すればそんなに難しくない気もします。自分が普段使っているCakephpの場合
投稿2016/10/16 21:10
編集2016/10/16 21:15総合スコア6586
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
実装方法次第でしょうけど基本的にスペースをandとみなし
かっこを別に解釈するだけなので冗長に処理すればよいかと
追記
一応PHP版、カラムの中からキーワードをマッチさせる場合
※hana-daさんの例をもとに、「and」はスペースなので無視してます
PHP
1function to_query($a){ 2 $pattern="/\s*OR\s*|\(\s*|\s*\)|\s+|[^\(\)\s]+/"; 3 $replacement=function($b){ 4 $pattern="/^\s+$/"; 5 if(preg_match($pattern,$b[0])) return " AND "; 6 $pattern="/\s*OR\s*|\(|\)/"; 7 if(!preg_match($pattern,$b[0])) return "`column` LIKE '%".$b[0]."%'"; 8 return $b[0]; 9 }; 10 $a=preg_replace_callback($pattern,$replacement,trim($a)); 11 return $a; 12} 13 14print '"A B C" -> '.to_query('A B C')."<br>"; 15print '"A (B OR C)" -> '.to_query('A (B OR C)')."<br>"; 16print '"A OR B OR C" -> '.to_query('A OR B OR C')."<br>"; 17print '"(A OR B) C" -> '.to_query('(A OR B) C')."<br>"; 18print '"(A OR B) C (D OR Z) (Z X)" -> '.to_query('(A OR B) C (D OR Z) (Z X)')."<br>"; 19print '" A ( B OR C ) " -> '.to_query(' A ( B OR C ) ')."<br>"; 20
投稿2016/10/16 15:46
編集2016/10/17 03:04総合スコア114572
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。