簡単なデータベース検索を行う

 Ajaxを使った最も簡単なデータベース検索を行ってみます。ここでは最もシンプルなタブ区切りテキストを利用します(実際のデータを見る)。元はExcelで作成したものです。Safariで文字化けをおこさないようにするためテキストエディタでBOM (Byte Order Mark) を付加してあります。
 検索する際には入力された文字列と一致するかどうかを調べる必要があります。その際、文字列が完全一致した場合だけデータをリストアップすると、やや不便です。そこでJavaScriptで利用できるmatch()を使って一致検索を行います。match()は正規表現で利用するメソッドですが、ここでは文字列の部分一致検索に利用します。今回のようなシンプルなものであればindexOf()を使って調べるものでも大丈夫です。
 入力された文字列とデータベースの文字が一致するかをmatch()で調べると結果は配列で返されます。ただし、一致しなかった場合には何のデータも返さずに結果はnullになります。これを利用して検索結果がnullでなかったら部分一致したとしてデータ(商品名と価格)を表示します。これをデータベースの項目の数だけ繰り返します。以下のスクリプトはテキストフィールドに文字を入力しリターンキーを押すか検索ボタンを押すと検索結果を表示するものです。(サンプルを実行する

2006/7/8追記:IEではsend()の後に記述された命令よりも先に通信処理が行われるようで、変数findTextの内容が最新のものになりません。このためsend()の後ではなく実際にfindeTextを利用する関数内でフォームデータを読み出す必要があります。IE6専用の実行スクリプトはsample1-2/index.htmlになります。(IE6用のサンプルを実行する


<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>一致したデータを表示する(非リアルタイム)</title>
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript"><!--
findText = "";
function loadDataFile(fName)
{
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET",fName,true);
httpObj.send(null);
findText = document.ajaxForm.requestText.value; // 検索する文字
}
}
function displayData()
{
if ((httpObj.readyState == 4) && (httpObj.status == 200))
{
$("result").innerHTML = parseTabText(httpObj.responseText);
}else{
$("result").innerHTML = "<b>Loading...</b>";
}
}
// タブ区切りテキストを解析して一致したデータを表示
function parseTabText(tabText)
{
var resultText = "<table border='1' cellspacing='0'>";
var LF = String.fromCharCode(10); // 改行コード (LF)
var TAB = String.fromCharCode(9); // タブコード
lineData = tabText.split(LF);
for (var i=0; i<lineData.length; i++)
{
itemData = lineData[i].split(TAB);
str = itemData[0].match(findText);
if (str)
{
resultText += "<tr><td>"+itemData[0]+"</td><td align='right'><b>"+itemData[1]+"</b>円</td></tr>";
}
}
resultText += "</table>";
return resultText;
}
// --></script>
</head>
<body>
<h1>一致したデータを表示する(非リアルタイム)</h1>
<p>タブ区切りテキストを読み込み一致したデータ項目を表示します</p>
<form name="ajaxForm" onSubmit="loadDataFile('sample.txt');return false">
<input type="text" value="メロン" name="requestText">
<input type="button" value="検索" onClick="loadDataFile('sample.txt')"><br>
</form>
<div id="result"></div>
</body>
</html>

 上記のスクリプトは文字列を入力し検索ボタンを押さないと結果が表示されません。Google サジェストなどでは文字を入力すると即座に結果が表示されます。このようにリアルタイムに検索結果を表示するスクリプトに改造しましょう。リアルタイムに結果を表示させる場合、テキストフィールドのonChangeイベントを使う方法とsetTimeout()やsetInterval()といったタイマーを利用する方法があります。ここではタイマーを0.5秒間隔で設定し定期的にテキストフィールドの文字列を読み出し検索を行います。
 setTimeout()は最初の引数が呼び出す関数、次が呼び出す間隔をミリ秒で指定します。ここでは0.5秒間隔なので500を指定します。今回のサンプルでは毎回サーバーからデータベースを読み出しているため、あまりに短い間隔で呼び出されると問題を引き起こす可能性があります。特に同じ文字列なのにサーバーにリクエストを出すのは、サーバーに負荷がかかりよくありません。このような場合、現在入力されている文字列と前回入力した文字列を比較し、異なる場合のみサーバーにリクエスト出して検索結果を表示するようにします。これでサーバーの負荷が軽減できます。実際のスクリプトは以下のようになります。(実際のサンプルを実行する

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>一致したデータを表示する(リアルタイム)</title>
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript"><!--
findText = findTextOld = "";
databaseFile = "sample.txt";
function loadDataFile(fName)
{
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET",fName,true);
httpObj.send(null);
}
}
function displayData()
{
if ((httpObj.readyState == 4) && (httpObj.status == 200))
{
$("result").innerHTML = parseTabText(httpObj.responseText);
}else{
$("result").innerHTML = "<b>Loading...</b>";
}
}
// タブ区切りテキストを解析して一致したデータを表示
function parseTabText(tabText)
{
var resultText = "<table border='1' cellspacing='0'>";
var LF = String.fromCharCode(10); // 改行コード (LF)
var TAB = String.fromCharCode(9); // タブコード
lineData = tabText.split(LF);
for (var i=0; i<lineData.length; i++)
{
itemData = lineData[i].split(TAB);
str = itemData[0].match(findText);
if (str)
{
resultText += "<tr><td>"+itemData[0]+"</td><td align='right'><b>"+itemData[1]+"</b>円</td></tr>";
}
}
resultText += "</table>";
return resultText;
}
function inputCheck()
{
findText = document.ajaxForm.requestText.value; // 検索する文字
if (findText != findTextOld)
{
loadDataFile(databaseFile);
findTextOld = findText;
}
setTimeout(" inputCheck()",500); // 0.5秒単位でチェック
}
window.onload = inputCheck;
// --></script>
</head>
<body>
<h1>一致したデータを表示する(リアルタイム)</h1>
<p>タブ区切りテキストを読み込み一致したデータ項目を表示します</p>
<form name="ajaxForm" onSubmit="return false">
<input type="text" value="メロン" name="requestText">
</form>
<div id="result"></div>
</body>
</html>

 この章まではサーバー側に全くCGIプログラムを用いない方法で通信しデータを表示してきました。しかし、ここまでではAjaxの魅力の半分ほどしか利用していないようなものです。次章ではサーバー側での処理について見てみましょう。

[第四章 1:従来のフォーム送信(CGI)とどう違うのか?へ]
[目次へ]

(2006.1.7, 2006.7.8)