0

電話番号プレフィックスに基づいてコールを適切なゲートウェイにルーティングする Java ベースのコール ルーティング エンジンを実装する必要があります。

ここで、プレフィックスを含む私のテーブル (postgres):

CREATE TABLE call_routing (
  prefix character varying(20) PRIMARY KEY NOT NULL,
  carrier character varying(50) NOT NULL,
  dialstring character varying(50) NOT NULL
)

いくつかのサンプルデータ:

INSERT INTO call_routing values ('02','1','/sofia/gateway/gw1');
INSERT INTO call_routing values ('0221','1','/sofia/gateway/gw2');
INSERT INTO call_routing values ('0228','1','/sofia/gateway/gw3');

たとえば、電話番号 0221123456789 はゲートウェイ「/sofia/gateway/gw2」にルーティングされ、電話番号 0211123456789 は「/sofia/gateway/gw1」にルーティングされる必要があります。

質問:

  1. 最も一致するプレフィックスを照会するための Java / jdbc での最速のアプローチは何でしょうか。
  2. アプリケーションの起動時にテーブルを Java オブジェクトに読み込み、各呼び出しでデータベースにアクセスせずに Java ですべてを行う方が良い方法ですか?
4

4 に答える 4

2

インデックス作成を改善する

長さ(プレフィックス)ではなく、プレフィックスで直接注文することにより:

SELECT dialstring FROM call_routing
WHERE number like prefix || '%'
ORDER BY prefix DESC
LIMIT 1

なんで?

数値の選択された行はabcdefプレフィックスになるためです。次のような数値になります。

ab abc abcd

したがって、それらをアルファベット順に並べると、長いものから短いものへのリストを取得するだけで十分であり、それが目的です。

また、次を使用してより強力なフィルターを取得できます。

prefix between 'a' and 'abcde'. すべての接頭辞は、アルファベット順>=で最も短い接頭辞になり、アルファベット順<=で最も長い接頭辞になります。

したがって、次のように表現できます。

SELECT dialstring FROM call_routing WHERE
prefix between substr(number, 1, 1) and number -- range filter (use index)
AND number like prefix || '%' -- only relevant data (normal filter)
ORDER BY prefix DESC -- index will work
LIMIT 1

そしてもちろん、インデックスは列のプレフィックスになります。

すべてキャッシュしますか?

はい、お願いします。:)

アイテムはいくつありますか?巨大なリストでない場合は、メモリにロードします。

次に、TreeMap (接頭辞で並べ替えたい場合) または HashMap (最初に最も長い接頭辞を見つけて、毎回 1 文字ずつ減らして試行し続ける場合) を使用できます。どちらが良いでしょうか?範囲内にあり、条件a >> abcdeに一致しないプレフィックスの数によって異なります (例による)。likeabbde

エントリー数が少ない場合

接頭辞 desc でソートされた配列を使用できます。

be
b
abcde
abbbc
abd
ab

適切なプレフィックスArrays.binarySearch(T[], T key, Comparator<T>)を見つけるには、電話がそこにあるかどうかを確認します ( abcde)。よかったら。そうでない場合は、次の時点まで先に進みます。

- you find a prefix (OK, this is the winner)
- it doesn't start with the same char (there are no prefix)

このようにして、範囲をトラバースしabcde >> a、最初のプレフィックス (可能な限り長い) を見つけます。

良いもの

TREEを作っています(名前はわかりません)。各ノードが文字 (この場合は数字) のみを保持するツリーを作成します。

0 // represents 0
 ->
   2  // represents 02
     -> 1 // represents 021
     -> 3 // represents 023
 ->
   4 // represents 04

したがって、最長のプレフィックスを探すときは、ツリーのできるだけ深い部分に到達しようとします。

Node n = root;
for (char c: number) {
    if ((child = n.hasChild(c)) != null)
    {
       prefix += c;
       n = child;
    }
    else
       break;
}

を作成するには が必要です

class Node
{
   int digit;
   Map<Integer, Node> childs = new HashMap<Integer, Node>(); // or a 10 bucket array :)
   YourInfo info;
}

そして、構造を作成するために:

findOrCreateNode(prefix).setInfo(info);

ここで、findOrCreateNode は前と同じですが、ノードが見つからない場合は... ノードを作成します ( n.put(c, new Node(c)))。

于 2012-08-31T11:53:02.767 に答える
1

私は個人的にテーブルをキャッシュしますが、長さで並べ替えることで、最も一致するプレフィックスを取得できます (number探しているものです)。

SELECT dialstring FROM call_routing WHERE strpos(number, prefix) = 1 ORDER BY length(prefix) DESC LIMIT 1;
于 2012-08-31T10:36:17.953 に答える
0

電話番号の高速プレフィックス マッチングを提供することを特に意図した github のこの PostgreSQL モジュールも参照してください: https://github.com/dimitri/prefix

于 2012-08-31T13:35:58.240 に答える
0

私はこれについて疑問に思っています。最大の問題は、キャッチオール (例では gw1) があることです。

SELECT dialstring from call_routing where number like prefix || '%'
ORDER BY length(prefix) DESC
LIMIT 1

これをインデックス化するのは難しいでしょうが、最初の質問は、追跡しているコール プレフィックスの数は?

于 2012-08-31T11:43:25.930 に答える