2012-03-15 4 views
2

나는 여러 페이지의 문서 (아마도 약 500 개 이상의 페이지) 사이에서 단어의 모든 발생을 인식하려고합니다. 나는 이미 단어가 나오는 페이지를 찾는 작업을 완료했습니다. 예를 들어 컴퓨터라는 단어가 나오는 모든 페이지를 나열하고 싶습니다.문서 단어 색인 데이터베이스 구조?

웹 서비스를 통해 신속하게 검색 할 수 있도록이 데이터를 저장하는 가장 좋은 방법은 무엇입니까?

테이블 구조 : VARCHAR (30) WORD, 방울 페이지

그리고 단어가 바로 다음 발생 위치를 페이지 필드는 모든 페이지의 쉼표로 구분 된 목록 수있는 내 본능은 그런 짓을하는 것입니다 그것을 분해하고 쿼리가 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를 추가 할 수 있습니다. 모두 귀하의 스펙과 파서로 가능한지 여부에 달려 있습니다.

당신이 주변에 검색하는 데 시간이있는 경우를위한 비효율적 인 공간 일반적으로하지만, 매우 좋은 연습입니다 정상화, 반대로 예를 들어/루씬 SOLR이 일

+0

Solr/Lucene에 대한 정보를 제공해 주셔서 감사합니다. 이 방향으로가는 끝낼 수도 있습니다! – Emeka

3

을 처리하는 방법 검색 엔진에서는 좀 봐 이 특별한 문제는 구조체를 고수하면서 BLOB의 페이지 목록을 BLOB 열의 내부에있는 비트 벡터로 대체 할 수 있습니다. 각 비트는 페이지를 나타냅니다. 장점은 500 페이지의 경우이 단어가 모든 페이지 (500/8 = 62.5)에 나타나더라도 한 단어에 대한이 벡터의 최대 크기는 63 바이트입니다.

비트 필드 안에는 각 페이지가 비트 번호에 해당합니다. 비트 번호 N이 ON이면 페이지 N에 단어가 표시되고 그렇지 않으면 N 페이지에 나타나지 않습니다. 이것은 다음과 같은 구조입니다. 기본적으로 사용됩니다 DBIx SQL text indexing implementation 비트는 오른쪽에서 왼쪽으로 번호가 지정되며 중요하지 않은 0은 제거 할 수 있습니다.

예를 들어 "컴퓨터"라는 단어가 3,4 및 12 페이지에 있으면 값은 100000001100 (십진수로 = 2060)이됩니다.

페이지에만 표시되는 경우 1 다음에 399 0's이 오는 숫자가됩니다. 모든 페이지에 나타나면 값은 1 자릿수의 500 배가됩니다.

저는 postgresql 데이터베이스에서 전체 텍스트 인덱싱 메일 내용에 대해 이러한 표현 (더하기 파티셔닝)을 사용 해왔고 아주 잘 수행되는 순진한 정규화 된 구현과는 달리 확장 성이 뛰어납니다. 작은 데이터 세트.

+0

결코 이런 식으로 생각하지 않았을 것입니다, 감사합니다! Johan의 대답은 비용이 많이 들지만 저장 한 데이터로 더 재미있는 일을 할 수 있다고 생각합니다. – Emeka

+1

@Emeka (좋은), 좋은 생각 David, 그러나 당신이 속력/우주 문제에 빠지기 전에 ** 역설 화하기 위해 템퍼링을하지 마십시오. 페이지에서 한 번 이상 나오는 단어를 어떻게 다룰 지 궁금합니다. (하지만 지금은 너무 깊어지고 있습니다.) – Johan