как правильно организовать поиск

вопрошатель
Дата: 08.10.2003 09:34:16
есть таблица слов, присутствующих в документе
table_word (id int, word char(12))
таблица документов
table_doc (id int, txt text)
и таблица индексов
table_index (doc, word)


хочется сделать чтобы как поисковой системе работало операции сложения и вычитания.

поиск по словам с операцией сложения типа :
+мама +ела +кашу сделать нетрудно

SELECT table_doc.id FROM (table_doc LEFT JOIN table_index ON table_doc.id=table_index.doc) LEFT JOIN table_word ON table_word.id=table_index.word WHERE
table_word.word IN ('мама', 'ела', 'кашу')

не могу придумать как сделать -папа -тоже -кушал, то есть вычитание из результата

помогите кто чем может :)

может есть где дока как правильно организовать парсер ?
zDIV
Дата: 08.10.2003 10:05:35
Наверняка можно упростить, то, что я предложу "в лоб" (без проверки синтаксиса) :)


SELECT s_table_doc.id FROM
(SELECT table_doc.id as sid FROM
(table_doc LEFT JOIN table_index ON table_doc.id=table_index.doc) LEFT JOIN
table_word ON table_word.id=table_index.word s_table_doc
WHERE table_word.word IN ('мама', 'ела', 'кашу')) as s_table_doc LEFT JOIN
table_index ON s_table_doc.sid=table_index.doc) LEFT JOIN
table_word ON table_word.id=table_index.word
WHERE NOT (table_word.word IN ('папа', 'тоже', 'кушал'))


Вот только бы, LEFT JOIN надо бы, по-моему, обязятельно заменить на INNER JOIN, особенно последний (который мой, точно!!!).
zDIV
Дата: 08.10.2003 10:08:35
Пардон...
  

SELECT s_table_doc.id FROM
(SELECT table_doc.id as sid FROM
(table_doc LEFT JOIN table_index ON table_doc.id=table_index.doc) LEFT JOIN
table_word ON table_word.id=table_index.word
WHERE table_word.word IN ('мама', 'ела', 'кашу')) as s_table_doc LEFT JOIN
table_index ON s_table_doc.sid=table_index.doc) LEFT JOIN
table_word ON table_word.id=table_index.word
WHERE NOT (table_word.word IN ('папа', 'тоже', 'кушал'))
zDIV
Дата: 08.10.2003 11:22:06
После двух первых select, наверное, следует добавить distinct...
вопрошатель
Дата: 08.10.2003 16:03:36
спасибо. теперь пришел более правильный вопрос. В запросе, как правило имеется 3 группы слов.

set A{ a1, a2, ... }
-без знака впереди - поисковик выбирает документы содержащие хотя бы одно слово из данной группы A.

+set B{ b1, b2, ...}
-затем из данного множества выбираются те,
что имеют все что имеют в описании все слова из множества B

-set C{c1, c2, ..}
и в окончании удаляются все, те что имеют хотя бы одно слово из множества C


кажется твой запрос этого не учитывает :(
вопрошатель
Дата: 09.10.2003 00:19:33
--zDIV
твой запрос синтаксически неверен, так как в финальном where table_word выходит из зоны описания таблицы, но даже после поправки твой запрос удаляет документ в которой есть -слова.

ты не учел, что набор слов для каждого документа сугубо индувидиальный


CREATE TABLE t_word (id int not null primary key, word nvarchar(12) not null unique)
INSERT INTO t_word(id,word) VALUES (1, 'мама')
INSERT INTO t_word(id,word) VALUES (2, 'ела')
INSERT INTO t_word(id,word) VALUES (3, 'каша')
INSERT INTO t_word(id,word) VALUES (4, 'папа')
INSERT INTO t_word(id,word) VALUES (5, 'кушал')
INSERT INTO t_word(id,word) VALUES (6, 'тоже')
INSERT INTO t_word(id,word) VALUES (7, 'девочка')
INSERT INTO t_word(id,word) VALUES (8, 'мальчик')
INSERT INTO t_word(id,word) VALUES (9, 'гулял')

--таблица документов
CREATE TABLE t_doc (id int not null primary key, txt nvarchar(200) not null)
INSERT INTO t_doc(id,txt) VALUES (1,'мама ела кашу тоже')
INSERT INTO t_doc(id,txt) VALUES (2,'папа мама мальчик')
INSERT INTO t_doc(id,txt) VALUES (3,'мальчик девочка тоже')
INSERT INTO t_doc(id,txt) VALUES (4,'папа мама тоже')
INSERT INTO t_doc(id,txt) VALUES (5,'папа гулял')
INSERT INTO t_doc(id,txt) VALUES (6,'мама папа гулял')

--и таблица индексов
CREATE TABLE t_idx (doc int not null , word int not null )
ALTEr TABLE t_idx ADD CONSTRAINT PK_idx PRIMARY KEY (doc, word)
ALTEr TABLE t_idx ADD CONSTRAINT FK_idxdoc foreign key (doc) REFERENCES t_doc(id)
ALTEr TABLE t_idx ADD CONSTRAINT FK_idxword foreign key (word) REFERENCES t_word(id)
INSERT INTO t_idx(doc, word) VALUES (1, 1)
INSERT INTO t_idx(doc, word) VALUES (1, 2)
INSERT INTO t_idx(doc, word) VALUES (1, 3)
INSERT INTO t_idx(doc, word) VALUES (1, 6)
INSERT INTO t_idx(doc, word) VALUES (2, 4)
INSERT INTO t_idx(doc, word) VALUES (2, 1)
INSERT INTO t_idx(doc, word) VALUES (2, 8)
INSERT INTO t_idx(doc, word) VALUES (3, 8)
INSERT INTO t_idx(doc, word) VALUES (3, 7)
INSERT INTO t_idx(doc, word) VALUES (3, 6)
INSERT INTO t_idx(doc, word) VALUES (4, 1)
INSERT INTO t_idx(doc, word) VALUES (4, 4)
INSERT INTO t_idx(doc, word) VALUES (4, 6)
INSERT INTO t_idx(doc, word) VALUES (5, 4)
INSERT INTO t_idx(doc, word) VALUES (5, 9)
INSERT INTO t_idx(doc, word) VALUES (6, 1)
INSERT INTO t_idx(doc, word) VALUES (6, 6)

если только список слов google > мама папа каша
то это работает правильно

SELECT txt FROM t_doc WHERE id IN (
SELECT distinct t_doc.id FROM (t_doc LEFT JOIN t_idx ON t_doc.id=t_idx.doc)
LEFT JOIN t_word ON t_word.id=t_idx.word WHERE
t_word.word IN ('мама', 'папа', 'каша') )

результат :

мама ела кашу тоже
папа мама мальчик
папа мама тоже
папа гулял
мама тоже

----------------------------------------------------------------
сложнее если есть запрос google > +мама +папа -каша

то есть все документы где есть мама и папа вмете и выкинуть тот где встречается каша.

не дайте умереть рубщику мяса. пжалуйста
вопрошатель
Дата: 09.10.2003 00:20:59
то есть результат должен быть :

папа мама мальчик
вопрошатель
Дата: 09.10.2003 00:22:20
упс. пардон

мама ела кашу тоже
папа мама мальчик
папа мама тоже
папа гулял
мама тоже

----------------------------------------------------------------
сложнее если есть запрос google > +мама +папа -тоже

то есть результат должен быть :

папа мама мальчик
f2f
Дата: 09.10.2003 11:29:57
Если запрограммировать алгоритм влоб то

В частном случае
SELECT txt FROM t_doc WHERE

id in ( select t_idx.doc from t_idx inner join t_word on t_idx.word=t_word.id where t_word.word in ( 'мама' ))
and id in ( select t_idx.doc from t_idx inner join t_word on t_idx.word=t_word.id where t_word.word = 'папа' )
and id not in ( select t_idx.doc from t_idx inner join t_word on t_idx.word=t_word.id where t_word.word in ( 'тоже' ))

Обобщая
SELECT txt FROM t_doc WHERE

id in ( select t_idx.doc from t_idx inner join t_word on t_idx.word=t_word.id where t_word.word in ( 'a1', 'a2' ))
and id in ( select t_idx.doc from t_idx inner join t_word on t_idx.word=t_word.id where t_word.word = 'b1' )
and id in ( select t_idx.doc from t_idx inner join t_word on t_idx.word=t_word.id where t_word.word = 'b2' )
and id not in ( select t_idx.doc from t_idx inner join t_word on t_idx.word=t_word.id where t_word.word in ( 'c1', 'c2' ))

Производительность не проверял
вопрошатель
Дата: 09.10.2003 18:12:29
спасибо - то что партия заказывала.