Search Serviceによる全文検索 (7/7)
作成:2012-06-02 15:26
更新:2012-06-02 15:26
更新:2012-06-02 15:26
■Searchのクエリー言語について
全データの検索ができたら、検索条件を設定しての検索まではあと一歩です。では、MyGaeAppServletサーブレットを更に拡張して、検索機能を追加することにしましょう。
先にフォームを作成するとき、<select>メニューに検索のための項目を用意しておきました。そこで、サーブレットのdoPostを修正し、メニューがfindだったら検索の処理を呼び出すように修正してみましょう。また検索処理のメソッドとして、findDocumentというメソッドを新たに追加することにします。
コードを修正したら、実際にデプロイして動作を確かめてみてください。この検索機能は、データの作成用に用意したフォームをそのまま利用します。タイトルまたはコンテンツの項目に検索テキストを書き、メニューから「データを検索」を選んで送信すると、フォームに記入した検索テキストを含むデータを一覧表示します。2つの項目それぞれにテキストを書いた場合には、どちらか一方が含まれていれば探し出します。
実際に試してみると、半角英数字のテキスト(英文ですね)と日本語のテキストが混じっていると、一部うまく見つけ出せないことがあるようです(例えば「Helloこんにちは」だとHelloが検索できない。Helloの後に半角スペースが必要)。が、日本語であればほぼ完璧に全文検索が機能することがわかります。
ここで作成したfindDocumentメソッドは、実は先ほどの全データを表示するgetAllDocumentとほとんど同じなのです。ソート関係の処理を省略しているという点(これがないとQuery作成はずいぶんとすっきりするのがわかるでしょう)と、Query.Builderをbuildする際、引数に以下のようなテキストを渡している点のみです。
1. 基本は、検索語をそのまま指定
一番簡単なクエリーの指定法、それは検索テキストをそのまま指定するというものです。これで、Documentのどのフィールドにあったとしても見つけてくれます。また複数の単語の場合、それらを半角スペースでつなげて記述すると、それらの単語のいずれかを含んでいれば探し出します。
2. フィールドを指定する場合は「フィールド名:検索語」とする
特定のフィールドからテキストを検索する場合は、「フィールド名:"検索テキスト"」というように、フィールド名の後にコロンで検索テキストをつなげます。
3. 複数の条件を設定する場合は「AND」「OR」でつなぐ
例えば「このフィールドに○○があるものと、こっちのフィールドに△△があるもの」というように、複数の条件を指定したい場合には、それらを「AND」や「OR」でつなぎます。例えば今回のサンプルでは、
4. 数値関係は等号・不等号を使える
今回は数値のフィールドはありませんが、数値のフィールドでは等号・不等号で条件を設定できます。例えば「price」というフィールドの値が100未満のものを検索したければ、「price < 100」とすればいいのです。また日時(Date)でも等号不等号は使えます。この場合は、例えば「datetime < 2012-1-1」というように、「年-月-日」という形式で日付を指定します。
――とりあえず、以上のクエリーの書き方だけ頭に入れれば、基本的な検索は行えるようになるでしょう。それぞれでいろいろと検索の仕方を試してみると面白いですよ。
先にフォームを作成するとき、<select>メニューに検索のための項目を用意しておきました。そこで、サーブレットのdoPostを修正し、メニューがfindだったら検索の処理を呼び出すように修正してみましょう。また検索処理のメソッドとして、findDocumentというメソッドを新たに追加することにします。
コードを修正したら、実際にデプロイして動作を確かめてみてください。この検索機能は、データの作成用に用意したフォームをそのまま利用します。タイトルまたはコンテンツの項目に検索テキストを書き、メニューから「データを検索」を選んで送信すると、フォームに記入した検索テキストを含むデータを一覧表示します。2つの項目それぞれにテキストを書いた場合には、どちらか一方が含まれていれば探し出します。
実際に試してみると、半角英数字のテキスト(英文ですね)と日本語のテキストが混じっていると、一部うまく見つけ出せないことがあるようです(例えば「Helloこんにちは」だとHelloが検索できない。Helloの後に半角スペースが必要)。が、日本語であればほぼ完璧に全文検索が機能することがわかります。
ここで作成したfindDocumentメソッドは、実は先ほどの全データを表示するgetAllDocumentとほとんど同じなのです。ソート関係の処理を省略しているという点(これがないとQuery作成はずいぶんとすっきりするのがわかるでしょう)と、Query.Builderをbuildする際、引数に以下のようなテキストを渡している点のみです。
String qstr = "title:\"" + title + "\" OR content:\"" + content + "\"";これは、検索の条件を指定する「クエリー」なのです。GAEのデータベースはSQLではありませんが、独自のクエリー言語(というほど大げさではありませんが)に基づいて検索条件を設定するようになっています。――では、Searchで使えるクエリーというのはどのようなものか。その基本を少し整理しましょう。
1. 基本は、検索語をそのまま指定
一番簡単なクエリーの指定法、それは検索テキストをそのまま指定するというものです。これで、Documentのどのフィールドにあったとしても見つけてくれます。また複数の単語の場合、それらを半角スペースでつなげて記述すると、それらの単語のいずれかを含んでいれば探し出します。
2. フィールドを指定する場合は「フィールド名:検索語」とする
特定のフィールドからテキストを検索する場合は、「フィールド名:"検索テキスト"」というように、フィールド名の後にコロンで検索テキストをつなげます。
3. 複数の条件を設定する場合は「AND」「OR」でつなぐ
例えば「このフィールドに○○があるものと、こっちのフィールドに△△があるもの」というように、複数の条件を指定したい場合には、それらを「AND」や「OR」でつなぎます。例えば今回のサンプルでは、
フィールド名1: "検索テキスト1" OR フィールド名2: "検索テキスト2"このように記述されていることがわかります。ORは「2つのいずれかが合致すればOK」という設定です。逆に「2つとも合致してないとダメ」という場合はANDを指定します。これらは条件だけでなく、複数のテキストを指定するのにも使えます。例えば、
title: ("Hello" OR "Hi") AND "BYE"こんな具合に設定すれば、titleフィールドにHelloかHiのどちらか、およびBYEの両方が含まれているものを探します。
4. 数値関係は等号・不等号を使える
今回は数値のフィールドはありませんが、数値のフィールドでは等号・不等号で条件を設定できます。例えば「price」というフィールドの値が100未満のものを検索したければ、「price < 100」とすればいいのです。また日時(Date)でも等号不等号は使えます。この場合は、例えば「datetime < 2012-1-1」というように、「年-月-日」という形式で日付を指定します。
――とりあえず、以上のクエリーの書き方だけ頭に入れれば、基本的な検索は行えるようになるでしょう。それぞれでいろいろと検索の仕方を試してみると面白いですよ。
(by. SYODA-Tuyano.)
※プログラムリストが表示されない場合
AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。
●プログラム・リスト●
※MyGaeAppServletの修正(doPostは置き換える) public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html"); request.setCharacterEncoding("utf8"); response.setCharacterEncoding("utf8"); session = request.getSession(); session.setAttribute("message", null); String param = request.getParameter("mode"); String title = request.getParameter("title"); String content = request.getParameter("content"); if ("create".equals(param)){ this.createDocument(title, content); } response.sendRedirect("/mygaeapp"); } public void findDocument(String title,String content){ String qstr = "title:\"" + title + "\" OR content:\"" + content + "\""; Index index = SearchServiceFactory.getSearchService() .getIndex(IndexSpec.newBuilder() .setName("mydataIndex")); try { Query query = Query.newBuilder() .setOptions(QueryOptions .newBuilder() .setLimit(10) .build()).build(qstr); // ★ Results<ScoredDocument> results = index.search(query); String result = "<table width=\"700\">"; for (ScoredDocument document : results) { String id = document.getId(); String title_str = document.getOnlyField("title") .getText(); String content_str = document.getOnlyField("content") .getText(); Date date = document.getOnlyField("datetime") .getDate(); result += "<tr><td>" + id + "</td><td>" + title_str + "</td><td>" + content_str + "</td><td>" + date + "</td></tr>"; } result += "</table>"; session.setAttribute("result",result); session.setAttribute("message", "検索 " + qstr + " を実行しました。"); } catch (SearchException e) { session.setAttribute("message", "検索に失敗しました。"); } }
※関連コンテンツ
「Google App Engine for Java(GAE/J)プログラミング入門」に戻る