クライアント側で検索する

 ここではクライアント側で郵便番号を検索します。まず、使用するデータですが、最初のサンプルでは前項で使用したKEN.txtを使います。郵便番号と住所のデータが, (カンマ)区切られたデータになっています。
 クライアント側で考えられるAjax的な検索方法としては、テキストフィールドに郵便番号が入力された時点で郵便番号データを読み込んで該当する住所があるか調べるといったところでしょう。ただ、この方法だと郵便番号データを読み込むまでに時間がかかってしまいます。5MBもあるため、とても実用には耐えられないでしょう。そこで、ページが読み込まれると同時に郵便番号データを読み込んでおきます。最初に読み込んでおくか、後で読むかの違いですが、郵便番号を入力して検索ボタンを押してから、数十秒〜一分近く反応がないよりマシでしょう。
 実際のスクリプトは以下のようになりますが、実行前に注意点があります。まず、Firefoxの場合、何度もスクリプトからの反応がない、という警告が表示されます。この場合、そのまま処理を継続しないと結果を得る事ができません。他のブラウザでは、警告は表示されませんが、使用しているマシン速度によっては1分以上無反応になることがあります。また、メモリが少ないマシンでは全く動作しないか、ハングアップしてしまう可能性も十分にあります。このような問題があるので、実行するかどうかは、よく考えてからにしてください。(サンプルを実行する

<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"><!--
zipData = "";
function loadDataFile()
{
var fName = "KEN.txt"; // 郵便局が提供している全国郵便番号データをアレンジしたもの
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET",fName,true);
httpObj.send(null);
}
}
function displayData()
{
if ((httpObj.readyState == 4) && (httpObj.status == 200))
{
zipData = httpObj.responseText;
$("result").innerHTML = "郵便番号データの読み込みが完了しました";
}else{
$("result").innerHTML = "郵便番号データを読み込み中...";
}
}
// カンマ区切りテキストを解析して一致したデータを表示
function parseZIPCode()
{
var resultText = "";
var findZipCode = $("zipCode").value;
var LF = String.fromCharCode(10); // 改行コード (LF)
lineData = zipData.split(LF);
for (var i=0; i<lineData.length; i++)
{
var itemData = lineData[i].split(",");
var ptr = itemData[0].indexOf(findZipCode);
if (ptr > -1) resultText +=itemData[1]+"<br>";
}
if (resultText == "") resultText = "該当する住所はありません";
$("result").innerHTML = resultText;
}
// --></script>
</head>
<body onload="loadDataFile()">
<h1>郵便番号検索(クライアントサイドで強引に処理)</h1>
<p>応答時間内に処理が完了しないため警告がでる場合があります</p>
<form name="ajaxForm" onSubmit="parseZIPCode();return false">
<input type="text" value="3990711" id="zipCode">
<input type="button" value="検索" onClick="parseZIPCode()"><br>
</form>
<div id="result"></div>
</body>
</html>

 さすがに、このような危険性&問題があるスクリプトをページ上に用意し使ってもらうというわけにはいきません。このようにデータが膨大(12万件)ある場合には、処理を工夫しないといけません。特に、上記のスクリプトは全てのデータを総当たりで調べているため非常に時間がかかってしまっています。
 まず、手軽に高速化で思いつくのが、郵便番号を規則的に並べておくというものです。使用している郵便番号データ (KEN.txt) は規則正しい順番で郵便番号が並んでいません。そこで、先頭の1桁の郵便番号だけ揃えたデータファイル (KEN2.txt) を作成します。この番号の位置を配列に入れておき、先頭の郵便番号に応じて検索する範囲を決定します。単純に12万件検索していたものが1/10の1万件程度になります。単純計算では10倍速度がアップしたことになります(もっとも、実際にはそんなに速度向上は見込めませんが)。以下が実際のスクリプトになります。(サンプルを実行する

<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"><!--
dataPoint = [1,14864, 18182, 24311, 35050, 45846, 57266, 75613, 87443, 99500, 122769 ];
zipData = "";
function loadDataFile()
{
var fName = "KEN2.txt"; // 郵便局が提供している全国郵便番号データをアレンジしたもの
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET",fName,true);
httpObj.send(null);
}
}
function displayData()
{
if ((httpObj.readyState == 4) && (httpObj.status == 200))
{
zipData = httpObj.responseText;
$("result").innerHTML = "郵便番号データの読み込みが完了しました";
}else{
$("result").innerHTML = "郵便番号データを読み込み中...";
}
}
// カンマ区切りテキストを解析して一致したデータを表示
function parseZIPCode()
{
var resultText = "";
var findZipCode = $("zipCode").value;
var LF = String.fromCharCode(10); // 改行コード (LF)
lineData = zipData.split(LF);
n = parseInt(findZipCode.charAt(0)); // 先頭の番号を取得
startPoint = dataPoint[n];
endPoint = dataPoint[n+1];
for (var i=startPoint; i<endPoint; i++)
{
var itemData = lineData[i].split(",");
var ptr = itemData[0].indexOf(findZipCode);
if (ptr > -1) resultText +=itemData[1]+"<br>";
}
if (resultText == "") resultText = "該当する住所はありません";
$("result").innerHTML = resultText;
}
// --></script>
</head>
<body onload="loadDataFile()">
<h1>郵便番号検索(ポインタを使って処理)</h1>
<p>応答時間内に処理が完了しないため警告がでる場合があります</p>
<form name="ajaxForm" onSubmit="parseZIPCode();return false">
<input type="text" value="3990711" id="zipCode">
<input type="button" value="検索" onClick="parseZIPCode()"><br>
</form>
<div id="result"></div>
</body>
</html>

 多少は高速化されましたが、やはり検索に時間がかかります。また、最初に大きいサイズのデータを読み込むため使用可能になるまで時間がかかります。このような手法では、サーバーには負荷はかかりませんが、ユーザーに負担がかかってしまい、良い結果にはなっていません。そこで、次項ではもう少し工夫して、高速に検索を行えるようにしてみます。

[第十章 3:高速化するへ]
[目次へ]

(2006.1.28)