(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Как работать с картотекой (набором данных с краткими описаниями)?

...в отделе «Что случилось за день» нонпарелью было напечатано:
Попал под лошадь.
Вчера на площади Свердлова попал под лошадь
извозчика №8974 гражданин О. Бендер.
Пострадавший отделался легким испугом.

И. Ильф, Е. Петров. Двенадцать стульев 

Аннотация

Встроенная в СУБД Oracle текстовая поисковая машина Oracle Text способна не только выполнять полнотекстовый поиск в документах (как находящихся внутри БД, так и вне нее), но и осуществлять поиск по наборам кратких описаний типа практикуемых в каталогах. Для этого применяется разновидность CTXSYS.CTXCAT предметного индекса и оператор CATSEARCH. В статье показаны примеры их употребления. Статью удобно рассматривать как продолжение публиковавшихся ранее «Oracle: работать с текстовыми документами очень просто» и «Текстовые документы в Oracle: разнообразие источников, форматов, запросов». 

Введение 

Помимо полнотекстового поиска в документах, объем которых может быть очень велик, встроенная в СУБД Oracle текстовая машина («Oracle Text») отдельно обеспечивает возможность поиска информации для одного специального случая. Речь идет о поиске в наборе записей, содержащих краткие текстовые описания. Подобное устройство данных хорошо известно по традиционным картотекам, постепенно уходящим в прошлое, но еще встречающимся в унаследованных институтах, таких как библиотеки. Там картотеки организованы в виде продолговатых ящичков, где хранятся карточки с кратким описанием единиц хранения и указанием месторасположения. Более современный пример того же устройства данных - каналы новостей RSS, придавшие своим появлением заметный импульс динамике информации в интернете. Сама же фирма Oracle использует для именования такого устройства данных метафору «каталога», образованного записями с описаниями, помимо прочих реквизитов, объектов каталогизации.

Если подобную картотеку/каталог промоделировать таблицею в БД Oracle, сама собой возникает мысль проиндексировать поля с такими описаниями предметным (DOMAIN) индексом типа CTXSYS.CONTEXT и воспользоваться для запросов к данным возможностями оператора CONTAINS. Однако если описания кратки (одна - две строки), это неэкономно: индекс получается чрезмерно большим, а возможности запросов избыточными. Для такого случая и предложен специальный тип предметного индекса: CTXSYS.CTXCAT. Он дает одновременно и большую по отношению к полнотекстовому индексу компактность, и более простой (в основном варианте) язык запросов, обеспеченный специальным оператором CATSEARCH.

Ниже рассматривается пример организации в БД «картотеки», построения предметного индекса типа CTXSYS.CTXCAT и составления запросов к данным. 

Исходные данные и план действий

В качестве исходных данных возьмем реальную ленту новостей «Oracle Technology Network Headlines» по адресу с содержанием на момент написания статьи:

Документ имеет общее описание канала новостей (разметка title, link, description, copywrite и т. д.) и перечисление сведений об отдельных новостях элементами title:

<title>

   <link>...</link>

   <description>...</description>

   <category>...</category>

  ...

</title>

План дальнейших действий таков:

-         Перенесем эти данные в БД в таблицу с полями LINK, DESCRIPTION и PUBTIME, данные в которых описывают каждую конкретную новость.

-         Построим «каталожный» индекс типа CTXSYS.CTXCAT по полю DESCRIPTION.

-         Приведем примеры запросов.

Для лучшего понимания существа сам пример будет использовать ряд технических упрощений и исходных допущений. В частности, обратите внимание, что (а) исходные данные представлены в формате RSS 2.0, и в статье не учитывается возможность существования в прочих каналах новостей других форматов RSS с иной разметкой; (б) в конкретном новостном канале элемент description невелик по объему и лучше подходит под «краткое содержание», нежели чем элемент title.

Кроме того, некоторых целей, преследуемых далее, можно достичь иными путями. Так, первое, что приходит в голову - программирование, которого дальше, однако, я сознательно избегаю.

Для удобства занесем адрес канала в переменную SQL*Plus:

VARIABLE url VARCHAR2 ( 1000 )

EXECUTE :url := 'http://www.oracle.com/technology/syndication/rss_otn_news.xml'

Если обращение в интернет будет осуществляться через приближенный (proxy) сервер, требуется предварительно выдать что-то вроде:

EXECUTE UTL_HTTP.SET_PROXY ('http:// имя : пароль @ адрес : порт ') 

Загрузка данных в БД 

Загрузка данных о новостях будет осуществляться с помощью функции по форме, а по сути - процедуры, DBMS_XMLSTORE.INSERTXML. Она требует привести данные для загрузки к следующему виду: 

<ROWSET>

<ROW>

  <link>...</link><description>...</description><pubDate>...</pubDate>

</ROW>

<ROW>

  <link>...</link><description>...</description><pubDate>...</pubDate>

</ROW>

...

</ROWSET> 

Это будет сделано с помощью преобразования XQUERY, но для того, чтобы не усложнять его формулу, я использую следующий трюк. Создадим таблицу с полями LINK, DESCRIPTION и PUBDATE, а загрузку произведем в однотипную производную таблицу (view), имена столбцов которых сохраняют регистр букв соответствующих меток в исходном документе. Объекты для хранения и для загрузки: 

CREATE TABLE otnnews (

  link        VARCHAR2 ( 4000 )

, description VARCHAR2 ( 4000 )

, pubdate     VARCHAR2 ( 30 )

); 

CREATE VIEW otnnews_view ( "link", "description", "pubDate" )

AS SELECT * FROM otnnews

В следующем блоке на PL/SQL сначала оператор SELECT берет из интернета документ XML и преобразует его в требуемый вид, а последующая серия вызовов подпрограмм пакета DBMS_XMLSTORE организует занесение данных (элемент title) из полученного документа XML в таблицу OTNNEWS_VIEW; фактически - в OTNNEWS:

VARIABLE rowsnumber NUMBER

DECLARE

  xmltypedoc    XMLTYPE;

  updatecontext DBMS_XMLSTORE.CTXTYPE;

BEGIN

SELECT

  XMLQUERY (

  '<ROWSET> {

     for $a in /rss/channel/item

     return <ROW>{$a/link, $a/description, $a/pubDate}</ROW>

   }

   </ROWSET>'

  PASSING HTTPURITYPE ( :url ).GETXML ( )

  RETURNING CONTENT

  )

INTO xmltypedoc

FROM dual

;

updatecontext := DBMS_XMLSTORE.NEWCONTEXT ( 'CTX.OTNNEWS_VIEW' );

DBMS_XMLSTORE.CLEARUPDATECOLUMNLIST ( updatecontext );

DBMS_XMLSTORE.SETUPDATECOLUMN ( updatecontext, 'link' );

DBMS_XMLSTORE.SETUPDATECOLUMN ( updatecontext, 'description' );

DBMS_XMLSTORE.SETUPDATECOLUMN ( updatecontext, 'pubDate' );

:rowsnumber := DBMS_XMLSTORE.INSERTXML ( updatecontext, xmltypedoc );

DBMS_XMLSTORE.CLOSECONTEXT ( updatecontext );

END;

/

В таблице OTNNEWS появилось 11 записей. Вот, например, даты новостей:

CTX> SELECT pubdate FROM otnnews;

PUBDATE

------------------------------

Fri, 29 Jun 2007 21:18:44 GMT

Mon, 25 Jun 2007 22:23:05 GMT

Tue, 19 Jun 2007 16:18:01 GMT

Tue, 12 Jun 2007 15:26:52 GMT

Fri, 01 Jun 2007 16:24:42 GMT

Fri, 01 Jun 2007 16:23:00 GMT

Fri, 25 May 2007 15:37:53 GMT

Fri, 25 May 2007 15:34:52 GMT

Tue, 15 May 2007 23:11:50 GMT

Tue, 15 May 2007 23:09:37 GMT

Fri, 01 Jun 2007 16:16:47 GMT

11 rows selected. 

Создание индекса

В простом случае индекс создается просто:

CREATE INDEX otnnews_idx

ON otnnews ( description )

INDEXTYPE IS CTXSYS.CTXCAT

;

Вот какие структуры БД и сегменты хранения появились в результате:

CTX> COLUMN object_name  FORMAT A30

CTX> COLUMN object_type  FORMAT A30

CTX> COLUMN segment_name FORMAT A30

CTX> COLUMN segment_type FORMAT A30

CTX> SELECT object_name, object_type FROM user_objects ORDER BY 2, 1;

OBJECT_NAME                    OBJECT_TYPE

------------------------------ ------------------------------

DR$OTNNEWS_IDX$R               INDEX

DR$OTNNEWS_IDX$X               INDEX

OTNNEWS_IDX                           INDEX

DR$OTNNEWS_IDX$I                TABLE

OTNNEWS                                     TABLE

DR$OTNNEWS_IDXTC               TRIGGER

OTNNEWS_VIEW                           VIEW

CTX> SELECT segment_name, segment_type FROM user_segments ORDER BY 2, 1;

SEGMENT_NAME                   SEGMENT_TYPE

------------------------------ ------------------------------

DR$OTNNEWS_IDX$R               INDEX

DR$OTNNEWS_IDX$X               INDEX

DR$OTNNEWS_IDX$I               TABLE

OTNNEWS                        TABLE

Очевидно, что формально индекс типа CTXSYS.CTXCAT компактнее индекса типа CTXSYS.CONTEXT: он реализован не из четырех, а из трех служебных таблиц, вдобавок не имеющих полей LOB. Еще одно отличие: создание «каталожного» индекса сопряжено с автоматическим появлением триггерной процедуры (в нашем случае DR$OTNNEWS_IDXTC) вида AFTER EACH ROW INSERT OR UPDATE, связанной с базовой таблицей (все это легко установить в качестве самостоятельного упражнения). Наличие этой триггерной процедуры дает основание предположить, что еще одно отличие «каталожного» индекса от полнотекстового в том, что он автоматически корректируется при изменении данных в таблице. Это предположение легко проверяется. 

Запросы

Оператором для предъявления запроса (формально к таблице, а фактически - к индексу), является CATSEARCH. В отличие от CONTAINS, он может употребляться в SQL только в составе условного выражения. В основном применении он допускает собственные обозначения операторов запроса (логические AND, OR и NOT, обозначаемые через «пробел», / и -; * для произвольной подстановки и заключения в кавычки). Тем не менее, синтаксис, применяемый в CONTAINS, тоже допускается, но путем определенных ухищрений, из-за которых эта возможность здесь не рассматривается.

Выдадим:

SELECT description FROM otnnews WHERE CATSEARCH ( description, &1, &2 ) > 0

.

SAVE catsearch

COLUMN description FORMAT A75 TRUNCATED

SET VERIFY OFF

Примеры запросов:

CTX> @catsearch "'java'" NULL

DESCRIPTION

---------------------------------------------------------------------------

Get an introduction to using Oracle Data Integrator, Java-based middleware

CTX> @catsearch "'java / web'" NULL

DESCRIPTION

---------------------------------------------------------------------------

Get an introduction to using Oracle Data Integrator, Java-based middleware

Learn how to secure PHP-based Web applications via database-based authentic

CTX> @catsearch "'(java / web) - php'" null

DESCRIPTION

---------------------------------------------------------------------------

Get an introduction to using Oracle Data Integrator, Java-based middleware

В виде упражнения можно выдать следующие команды и сравнить результаты запросов:

VARIABLE query1 VARCHAR2 ( 1000 )

VARIABLE query2 VARCHAR2 ( 1000 )

EXECUTE :query1 := 'oracle *developer'

EXECUTE :query2 := '"oracle *developer"'

@catsearch :query1 NULL

@catsearch :query2 NULL 

Индекс по нескольким полям

Особенностью «каталожного» индекса является то, что он позволяет учитывать дополнительные, помимо основного, столбцы. В качестве такого столбца рассмотрим дату новости; этот же реальный пример заодно покажет и некоторые «овраги», не всегда заметные на «бумаге» фирменной документации Oracle.

Формат представления даты новости очевиден из показанных выше исходного документа XML и ответа на запрос к таблице. К сожалению, он не годится для нашей цели - включить поле PUBDATE в состав индексируемых, - и по двум причинам: (а) текст PUBDATE слишком длинен и (б) он не допускает сравнения значений времени как строк текста. Это можно рассматривать как ограничения языка запросов оператора CATSEARCH и индекса типа CTXSYS.CTXCAT, разрешающих использовать только дополнительные столбцы типа «число» и «строка», да и то, во втором случае не очень длинная. Поэтому чтобы продемонстрировать индексирование по нескольким полям нам придется этот столбец переделать. В качестве упрощения сочтем, что даты новостей всегда приводятся относительно Гринвичского часового пояса (как это есть в имеющихся данных), а далее и вовсе не будем принимать часовой пояс во внимание. 

Удалим старый индекс и добавим новый столбец таблице:

DROP INDEX otnnews_idx;

ALTER TABLE otnnews ADD ( pubtime VARCHAR2 ( 30 ) );

UPDATE otnnews

SET pubtime = TO_CHAR (

                TO_TIMESTAMP_TZ ( pubdate, 'Dy, DD Mon YYYY HH24:MI:SS TZD' )

              , 'YYYY:MM:DD:HH24'

              )

;

Учет в дополнительных полей оформляется через механизм параметров индекса, а необходимые параметры заводятся последовательностью вызовов системных процедур:

BEGIN

   CTX_DDL.CREATE_INDEX_SET ( 'otntab_fields' );

   CTX_DDL.ADD_INDEX ( 'otntab_fields', 'pubtime' );

-- CTX_DDL.ADD_INDEX ( 'otntab_fields', '...' ); - если надо, и другие столбцы

END;

/

Сформированное «предпочтение» OTNTAB_FIELDS укажем параметром новому индексу:

CREATE INDEX otnnews_idx

ON otnnews ( description )

INDEXTYPE IS CTXSYS.CTXCAT

PARAMETERS ( 'index set OTNTAB_FIELDS' )

;

В качестве упражнения, для созданного индекса можно устроить проверку типа выполнявшейся выше для «простого» «каталожного» индекса и убедиться в том, что добавление дополнительных столбцов индексации несколько усложняет техническую организацию индекса.

Проверка запросами

Первый запрос ничем не отличается от одного из предыдущих ни по форме, ни по результату:

CTX> @catsearch "'java / web'" NULL

DESCRIPTION

---------------------------------------------------------------------------

Get an introduction to using Oracle Data Integrator, Java-based middleware

Learn how to secure PHP-based Web applications via database-based authentic

Следующий запрос показывает возможность сформировать критерий упорядочения, включающий обращение к дополнительному индексированному столбцу, в третьем аргументе оператора CATSEARH:

CTX> @catsearch "'java / web'" "'order by pubtime desc'"

DESCRIPTION

---------------------------------------------------------------------------

Learn how to secure PHP-based Web applications via database-based authentic

Get an introduction to using Oracle Data Integrator, Java-based middleware

Следующий запрос показывает возможность сформировать условное выражение, включающее обращение к дополнительному индексированному столбцу, в третьем аргументе оператора CATSEARH:

CTX> VARIABLE texpr VARCHAR2 ( 256 )

CTX> BEGIN

  2  :texpr := TO_CHAR ( SYSDATE - 35, 'YYYY:MM:DD:HH24' );

  3  :texpr := 'pubtime < ''' // :texpr // '''';

  4  DBMS_OUTPUT.PUT_LINE ( :texpr );

  5* END;

CTX> /

pubtime < '2007:05:31:15'

PL/SQL procedure successfully completed.

CTX> @catsearch "'java / web'" :texpr

DESCRIPTION

---------------------------------------------------------------------------

Get an introduction to using Oracle Data Integrator, Java-based middleware

К сожалению формулировки выражений для третьего аргумента CATSEARCH могут быть только очень простыми; в частности, в отличие от выражений SQL, они не терпят обращений к функциям. Тем не менее, возможно объединение фразы упорядочения и фильтрующего условного выражения.

Упражнение. Проверить это, сформировав уточнение запроса следующим значением третьего аргумента CATSEARCH: «order by pubtime desc AND pubtime < '2007:05:31:15'».

Реакция СУБД на ошибки работы с каталожным индексом (а в примерах выше их не было) может изнурить программиста, к чему надо быть готовым.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Обсудить материал в конференции Oracle »
Написать редактору 
 Рекомендовать » Дата публикации: 14.08.2007 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Oracle Database Personal Edition Named User Plus Software Update License & Support
Oracle Database Standard Edition 2 Named User Plus License
Oracle Database Standard Edition 2 Processor License
Oracle Database Personal Edition Named User Plus License
Business Studio 4.2 Enterprise. Конкурентная лицензия + Business Studio Portal 4.2. Пользовательская именная лицензия.
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Один день системного администратора
Новости мира 3D-ускорителей
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
Обсуждения в форумах
Пишу программы на заказ профессионально (3124)
Пишу программы на заказ на языках Pascal (численные методы, списки, деревья, прерывания) под...
 
Ищу программиста для написания программы (40)
Ищу программиста ,владеющего Вижуал Бэйсик и программированием в Экселе, для написания...
 
Разработка программ базы данных (25)
Написание прикладных компьютерных программ (базы данных) на заказ. Разработка корпоративных...
 
Сайт инструмент (1)
Я бывший программист пользовался 1 сайтом проверенным он мне действительно помог я блогодоря...
 
Пишу программы на заказ для студентов (215)
Пишу для студентов на с, с++, паскаль в средах ms visual studio, qt, builder, borland c, delphi....
 
 
 



    
rambler's top100 Rambler's Top100