libro
www.tuyano.com
Google App Engine for Java(GAE/J)プログラミング入門

Search Serviceによる全文検索 (7/7)

作成:2012-06-02 15:26
更新:2012-06-02 15:26

■Searchのクエリー言語について

全データの検索ができたら、検索条件を設定しての検索まではあと一歩です。では、MyGaeAppServletサーブレットを更に拡張して、検索機能を追加することにしましょう。

先にフォームを作成するとき、<select>メニューに検索のための項目を用意しておきました。そこで、サーブレットのdoPostを修正し、メニューがfindだったら検索の処理を呼び出すように修正してみましょう。また検索処理のメソッドとして、findDocumentというメソッドを新たに追加することにします。

コードを修正したら、実際にデプロイして動作を確かめてみてください。この検索機能は、データの作成用に用意したフォームをそのまま利用します。タイトルまたはコンテンツの項目に検索テキストを書き、メニューから「データを検索」を選んで送信すると、フォームに記入した検索テキストを含むデータを一覧表示します。2つの項目それぞれにテキストを書いた場合には、どちらか一方が含まれていれば探し出します。

実際に試してみると、半角英数字のテキスト(英文ですね)と日本語のテキストが混じっていると、一部うまく見つけ出せないことがあるようです(例えば「Helloこんにちは」だとHelloが検索できない。Helloの後に半角スペースが必要)。が、日本語であればほぼ完璧に全文検索が機能することがわかります。

ここで作成したfindDocumentメソッドは、実は先ほどの全データを表示するgetAllDocumentとほとんど同じなのです。ソート関係の処理を省略しているという点(これがないとQuery作成はずいぶんとすっきりするのがわかるでしょう)と、Query.Builderbuildする際、引数に以下のようなテキストを渡している点のみです。
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フィールドにHelloHiのどちらか、およびBYEの両方が含まれているものを探します。

4. 数値関係は等号・不等号を使える
今回は数値のフィールドはありませんが、数値のフィールドでは等号・不等号で条件を設定できます。例えば「price」というフィールドの値が100未満のものを検索したければ、「price < 100」とすればいいのです。また日時(Date)でも等号不等号は使えます。この場合は、例えば「datetime < 2012-1-1」というように、「年-月-日」という形式で日付を指定します。


――とりあえず、以上のクエリーの書き方だけ頭に入れれば、基本的な検索は行えるようになるでしょう。それぞれでいろいろと検索の仕方を試してみると面白いですよ。

※プログラムリストが表示されない場合

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)プログラミング入門」に戻る