2012-03-15 9 views
2

私は、ドキュメントのいくつかのページ(おそらく約500以上のページ)の間に単語の出現をすべて認識することを考えています。私はすでに単語が出現するページを見つける作業を行っています。たとえば、コンピュータという言葉が出現するすべてのページをリストしたいとします。文書索引データベース構造?

ウェブサービス経由でこのデータをすばやく検索できるようにするにはどうすればよいでしょうか?

テーブルの構造:: VARCHAR(30)WORD、ブロブPAGES

とページフィールドは言葉だけで、その後に発生し、すべてのページのカンマ区切りのリストも持っている私の本能はちょうど何かなどを行うことですそれを分解して、クエリがWORDフィールドに一致するとすべてのページを一覧表示します。私はこれを達成するより効率的な方法があるかどうか疑問に思っていますか?私はMySQLとPHP/Zendを使用している可能性が高いのは、それが私が最もよく知っていることだからです。しかし、あなたが良いアイデアを持っていれば、私はそれらを聞くことができます。

ドキュメント内のすべてのユニークワードに対してローが必要なため、テーブルが非常に長くなる可能性があります。おそらく、私は3文字または4文字よりも短い文字列に制限を設定していましたが、それでもなお10-20kワード以上を想像していました。私は行のリストをアルファベット順に並べれば、私のデータベースサーバでどうにかして簡単にできますか? (つまり、リンゴ、リンゴ、ブランチは昇順になっていますか?)MySQLはこれを処理できますか?他の何かがそれをより良く扱うことができますか?

最後に、興味のあるデータを収集/提供できる構造スキーマがありますか? (すなわち、ユーザに近接して現れることが多い関連する単語を与えるなど)

答えて

4

あなたはデータベースを正規化する必要があります。

まずページ

table pages (
    id unsigned integer auto_increment primary key, 
    page blob, 
    other_interesting_data_about_a_page) 

を格納するテーブルには、その単語を保持するための表では、今、あなたページ

table word_page (
    word_id unsigned integer, 
    page_id unsiged integer, 
    pos_in_page unsigned integer, /*position*/ 
    primary key pk (word_id, page_id, pos_in_page)) 

に単語をリンクするテーブル次に

table wc (
    id unsigned integer auto_increment primary key 
    word varchar(20) unique key, 
    count unsigned integer default 1, 
    other_interesting_data_about_a_word....) 

をカウントページ内の単語数を問い合わせることができます:

SELECT COUNT(*) 
FROM word_page 
WHERE page_id = 123 

またはページ内で単語 'the'が繰り返される回数。

SELECT COUNT(*) 
FROM word_page wp 
INNER JOIN wc ON (wp.word_id = wc.id) 
WHERE wp.page_id = 123 AND wc.word = 'the' 

警告の言葉をおよびページ・フィールドは、すべてのページ.....

のカンマ区切りのリストである必要があり、これまで、これまでにCSVを使用しないでくださいデータベースは、あなたが今までに使用できる最悪のアンチパターンです。それが落ちれば、何度も何度もあなたを噛んでしまいます。
もし必要があると感じたら、衝動がなくなるまで頭の中で自分を蹴り、次に別のテーブルを使用してください。

+0

私は決してデータベースでCSVを使用しません。 :)ヒントをありがとう! – Emeka

1

簡単にメンテナンスやインデックスのために、私は計算されたprimareyキーでマッピングテーブルを設定します: ID BIGINT AUTO_INCREMENT、 単語VARCHAR(30)、 ページINT、 ... との両方のためのインデックスを作成します単語とページ。 この方法では、柔軟性があり、リストを爆発させる必要がなく、いくつかの統計情報(よりユニークな単語などを使用するページ)にアクセスする必要もありません。

MySQL(および他のすべてのリレーショナルDBエンジン)は、ツリー構造を使用して内部インデックスを作成します。データを事前にソートする必要はありません。

この表はMySQLによって容易に処理されます。より高速な他のDBエンジンがあるかもしれませんが、それは大丈夫です。

もちろん、word、other_word、distanceなどのテーブルを追加することもできます。すべては仕様やパーザの可能性に依存します。

あなたの周りにブラウズするためにいくつかの時間を持っている場合は、のために、非効率的なスペース一般けどかなり良い習慣をある正規化とは対照的に、たとえば/ LuceneをSolrにはこの物事

+0

Solr/Luceneのヒントをありがとう。この方向に向かうかもしれない! – Emeka

3

を扱っている、どのようsearchenginesを見てみましょうこの特定の問題は、あなたの構造に固執したいかもしれませんが、あなたのブロブのページのリストを、各ビットがページを表すビットのベクトル(ブロブの列の中にあります)で置き換えてください。利点は、500ページの場合、このワードがすべてのページに表示されても(500/8 = 62.5)、1ワードのこのベクトルの最大サイズは63バイトになります。

ビットフィールド内では、各ページはビット番号に対応します。ビット数Nがオンの場合は、ページNにワードが表示されます。そうでない場合はページNに表示されません。 これは基本的にはDBIx SQL text indexing implementationによって使用されます。 ビットは右から左に番号が付けられ、重要でない0は削除されます。

たとえば、「コンピュータ」という単語が3,4および12ページにある場合、値は 100000001100(10進表記では2060)になります。

ページ400にのみ表示される場合は、1の後に399 0'sの数字が表示されます。すべてのページに表示されている場合、数値は1の500倍になります。

私はpostgresqlデータベースのフルテキストインデックスのメールコンテンツにその表現(およびパーティション化)を使用してきましたが、非常にうまく機能する純粋な正規化された実装とは対照的に、小さなデータセット。

+0

このようなことは決して考えなかったでしょう、ありがとう!私はヨハンの答えがより高価ですが、私はラインの下に格納されたデータでより面白いことをすることができますと思う。 – Emeka

+1

@Emeka(同様に)、素敵なアイデアDavid、しかしあなたがスピード/スペースの問題にぶつかる前に、デノーマライズするためにテンションを上げないでください。私はあなたがページ上で複数回出現する言葉にどう対処するのだろうかと思います(しかし、私は今、あまりにも深くなっています)。 – Johan