質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

1回答

2139閲覧

Flaskで複数条件での検索機能を実装したい

kou2014

総合スコア0

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2023/01/26 14:57

前提

現在、Flaskを利用してウェブアプリケーションを作成しています。

そこにSQLを用いた検索機能を実装したいのですが、
現在のコードでは検索ワードを何も入力していない項目がある場合、検索結果にテーブル内の全レコードが表示されるなど正常に検索されません。

何か良い方法はありますでしょうか。

処理の流れとしては、

  1. HTMLからPOST送信
  2. Flaskで受け取り
  3. localhost内のMariaDBにselect文で検索
  4. render_templateでselect文の実行結果を送信

という流れにしたいです。

また、検索ワードは

  • text1は部分一致検索
  • text2~3は完全一致検索
  • ラジオボタンは必ずどちらか選択されている

となっています。

実現したいこと

  • 検索ワードが入力されていない項目を条件から外す(もしくは無視する)

ソースコード

検索画面

HTML

1<!-- search.html --> 2 3<form action="{{ url_for('search') }}" method="post"> 4 text1: 5 <input type="text" name="text1"> 6 text2: 7 <input type="text" name="text2"> 8 text3: 9 <input type="text" name="text3"> 10 radio: 11 <input type="radio" value="radio1"> 12 <input type="radio" value="radio2" > 13 <input type="submit" value="検索"> 14</form>

検索結果

HTML

1<!-- result.html --> 2 3{% for res in result %} 4 <tr> 5 <td class="col-2"> 6 {{ res.text1' }} 7 </td> 8 <td class="col-2"> 9 {{ res.text2 }} 10 </td> 11 <td class="col-2"> 12 {{ res.text3 }} 13 </td> 14 <td class="col-2"> 15 {{ res.radio }} 16 </td> 17 </tr> 18{% endfor %}

Flask

Python

1# app.py 2 3@app.route("/search", methods=["POST"]) 4def search(): 5 text1 = '%' + request.form.get("text1") + '%' 6 text2 = request.form.get("text2") 7 text3 = request.form.get("text3") 8 radio = request.form.get("radio") 9 dbmg = db_manager.db_manager() 10 11 sql ="select * from db where text1 like %s or text2=%s or text3=%s or radio=%s" 12 result = dbmg.exec_query(sql,(text1,text2,text3,radio)) 13 return render_template("result.html", result=result)

DB処理

Python

1# db_manager.py 2 3import pymysql 4import pymysql.cursors 5 6class db_manager(): 7 def connect(self): 8 return pymysql.connect( 9 host="localhost", # DBサーバのアドレス 10 user=***, # DBのユーザ名 11 passwd=***, 12 db="app", # 接続するDB名 13 charset="utf8", # 文字コード 14 cursorclass=pymysql.cursors.DictCursor # 検索結果のデータ型(辞書型) 15 ) 16 17 def exec_query(self,sql,params=()): 18 with self.connect() as conn : 19 with conn.cursor() as cursor: 20 cursor.execute(sql,params) 21 results = cursor.fetchall() 22 conn.commit() 23 24 return results

試したこと

if文で検索ワードの有無を判定して条件分岐させる(現実的ではないと思い中止)

補足情報(ツールのバージョン)

Python3(Flask・PyMySQL)
MariaDB
Ubuntu
Apache

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2023/01/26 15:43

> if文で検索ワードの有無を判定して条件分岐させる(現実的ではないと思い中止) 上記はどういう理由で「現実的ではない」と判断されたのでしょうか?
kou2014

2023/01/27 12:23

if文で書くとなると条件がかなり多くなってややこしくなり、現実的ではないと思って早々に諦めました。 でも、SQLで書く場合はそうするしかないのかなと思ってます。
guest

回答1

0

SQLアンチパターンによると、kou2014さんの質問は、クエリのアンチパターンの内「プアマンズ・サーチエンジン(貧者のサーチエンジン)」にあたるものだと思いますので、今四苦八苦している実装はすべきではないというのが回答になると思います。

SQLアンチパターンに記載されている解決策は、「全文検索エンジンを使え」と書かれており、全文検索エンジンにはベンダー拡張のものや、サードパーティーのサーチエンジン(Sphinx Search, Apache Lucence)があると記載されています。

MariaDBにも全文検索エンジンあるようです。
MariaDBの全文検索を試したら感動した話

他にもElasticsearchなども有名で、色々な製品がありますので、使いやすいのを調べて見てはいかがですか?

現在のコードでは検索ワードを何も入力していない項目がある場合、検索結果にテーブル内の全レコードが表示されるなど正常に検索されません。

それでも無理矢理SQL(LIKE)で書きたい場合は、入力値が無い場合をパターン化して、if文で分岐するしかないと思います。

if文で検索ワードの有無を判定して条件分岐させる(現実的ではないと思い中止)

とありますが、どの辺に「現実的ではない感」を感じたのでしょうか?
text2,3とは完全一致するもの検索するなら、ここに何も入っていない物とマッチするものは存在しないとか、そういう結果になりそうなのですが、何か違う理由があるのでしょうか。

投稿2023/01/27 01:30

FiroProchainezo

総合スコア2401

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kou2014

2023/01/27 12:19

回答ありがとうございます。全文検索エンジンというのがあることを初めて知りました。自分でも調べて検討してみます。 if文で書くとなるとかなり長くなってややこしくなると思い現実的ではないと感じたのですが、SQLで書く場合はやっぱりその方法しか無いですよね… text1,2,3について補足させていただくと、1はキーワード検索のためFlaskで受け取った際に前後に%を付与して後々SQLに代入する際に部分一致になるようにして(Flask 行5)、2と3はドロップダウンリスト(ワードはDBのフィールドと合致する)にする予定だったのでそのまま受け取って(Flask 行6,7)、SQLに代入(Flask 行11)して検索をかけ、全ての条件に当てはまるレコードを返すという処理です。その際何も入力されていない項目があると検索結果がおかしくなります。(ORでつなげているのが原因だと推察)
FiroProchainezo

2023/01/27 12:43

ややこしくなるのは仕方ないんじゃないかと思います。 パラメータが増えるとややこしく(複雑に)なるものじゃないですかね。 質問では聞かれていないですが、FlaskでSQLを使う場合、Flask-SQLAlchemyを使うのが一般的です。 Flask-SQLAlchemyを使えばSQLインジェクションなどを防ぐことができます。 とはいっても、入力値はescape処理をしないで使うべきではないです。 そのまま使うのではなく、escapeしてから使って下さい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問