2010-03-16 3 views
2

У меня есть текстовый столбец в таблице. Мы храним XML в этом столбце. Теперь я хочу, чтобы искать по тегам и значенияPostgreSql XML Текстовый поиск

Пример данных:

<bank> 
    <name>Citi Bank</name> 
    ..... 
    ..... 
/<bank> 

Я хотел бы выполнить следующий запрос:

выберите * от хххх, где to_tsvector («английский», xml_column) @ @ to_tsquery ('<name>Citi Bank</name>')

Это прекрасно работает, но также работает с тегами, такими как name1 или no tag.

Как мне настроить мой поиск, чтобы это работало, поэтому я получаю точное соответствие для тега и значения?

ответ

2

Вы можете использовать функцию XPATH как этот

select * 
from xxx 
where xpath(xml_column, 'bank/name/text()') = 'CitiBank'; 

НО он не будет использовать индекс полнотекстового поиска. Вы можете использовать подзапрос, чтобы находить вероятные совпадения и избегать полных сканирований, а также выражение xpath для получения правильных ответов или создавать индекс функции, если запросы всегда будут одинаковыми.

+0

xml_column не имеет типа xml, это обычный текст. Я пробовал с xpath, но индексирование не работает .... длинный рассказ. Мне нужно сделать эту работу простым текстовым поиском – cro

+0

Я не думаю, что ее можно использовать только с текстовыми индексами. Вы можете попробовать комбинированный подход, используя XMLPARSE, чтобы передать текст в xml, чтобы вы могли использовать выражения xpath и полное текстовое выражение, которое у вас уже есть, во избежание полного сканирования. – Samuel

+0

Привет, вы должны использовать '// text()', поэтому 'array_to_string (xpath ('path // text()', content) :: text [], '')' для получения всего текста, например, HTML-документ со многими внутренними тегами. –

1

Возможно, вам захочется пересмотреть хранение XML в базе данных, вместо этого вы можете посмотреть на вставку данных в связанные таблицы, поскольку использование XML является плохой заменой реляционного хранилища. Даже если вы идете с XML в базе данных, используйте тип XML, а не тип TEXT, и создать индекс, как это (да, в принципе вы должны были бы индекс за выражение XPath):

CREATE INDEX my_funcidx ON my_table USING GIN (CAST(xpath('/bank/name/text()', xmlfield) AS TEXT[])); 

затем, запрос это так:

SELECT * FROM my_table WHERE CAST(xpath('/bank/name/text()', xmlfield) AS TEXT[]) @> '{Citi Bank}'::TEXT[]; 

, и это будет использовать индекс, как указывает EXPLAIN.

Важной частью является CASTing to TEXT [], поскольку XML [], возвращаемая функцией xpath, по умолчанию не индексируется.

+0

Спасибо за пример .... Я пробовал, и он, кажется, не использует индекс. как вы заявляете (да, в основном вам нужен индекс на выражение xpath): вероятно, это пробная пробка. Моя идея теперь, используйте текстовый столбец, сначала найдите ts_tovector @@ ts_toquery, как только у меня получится. Я загружаю xml в память и выполняю запрос Xpath в памяти. первые результаты многообещающие – cro

+0

вы действительно будете делать много разных запросов xpath (а не только одни и те же запросы с разными параметрами)? Я думаю, что это сильно выиграет от разбиения на реляционные таблицы, возможно даже на триггер вставки или обновления. Это было указано, каков был ваш индекс и план выполнения вашего запроса на основе моего примера. – MkV

+0

Привет, вы должны использовать '// text()', поэтому 'array_to_string (xpath ('path // text()', content) :: text [], '')' для получения всего текста, например, HTML-документ со многими внутренними тегами. –

Смежные вопросы