امکان جستجو در سطح کل دیتابیس با DBMS_SEARCH – اوراکل 23c

در نسخه 23c، اوراکل پکیجی را به نام DBMS_SEARCH معرفی کرده است که می تواند با استفاده از زیرساخت ORACLE TEXT و حذف پیچیدگی های آن، امکان جستجو را بر روی Objectهای مختلف فراهم کند. پکیج DBMS_SEARCH با ایجاد ایندکسی از نوع JSON Search Index می تواند قابلیت جستجو را بر روی sourceهای مختلف اعم از Table و View فراهم کند.

برخلاف ایندکسهای متعارف نظیر Btree و Bitmap که بر روی ستونهای یک جدول قابل ایجاد هستند، ایندکسی که از طریق پکیج DBMS_SEARCH ایجاد می شود، می تواند چندین جدول و ویو را به عنوان source بپذیرد و جستجوی همزمان را بر روی این sourceها انجام دهد.

جداولی که به عنوان سورس تعیین می شوند می توانند حاوی ستونهایی با نوع داده number، varchar، CLOB، JSON و … باشند و محدودیتهای بسیاری کمی در این زمینه وجود دارد ضمنا اضافه کردن source به ایندکس به راحتی و صرفا با اجرای یک دستور امکان پذیر است.

توجه! ایندکسهایی که از طریق این پکیج ایجاد می شوند، بروزرسانی آنها به صورت خودکار انجام می شود(sync on commit).

در ادامه با نحوه ایجاد این نوع از ایندکس، اضافه کردن source به آن و همچنین انجام جستجو از طریق آن آشنا خواهیم شد.

در ابتدا جداول و ویوهایی را ایجاد می کنیم تا بتوانیم از این جداول و ویو به عنوان sourceهای ایندکسی که از طریق DBMS_SEARCH ایجاد می کنیم، استفاده کنیم:

SQL> create table IranTBL1(id number primary key,des varchar2(1000));
Table created.
SQL> insert into IranTBL1 values(1,'www.usefzadeh.com');
1 row created.
SQL> create table IranTBL2(id number primary key,des1 varchar2(1000),des2 CLOB,des3 JSON);
Table created.
SQL>  insert into IranTBL2 values(1,'My name is Vahid','this is a test', '{"name":"vahid", "last_name" :"usefzadeh"}');
1 row created.

در قدم اول، با استفاده از پروسیجر CREATE_INDEX از بسته DBMS_SEARCH ایندکسی را ایجاد می کنیم در زمان ساخت ایندکس می توان tablespaceای را هم برای آن تنظیم نمود:

SQL> create tablespace TBLSP_Search_IDX ;
Tablespace created.
SQL> exec DBMS_SEARCH.CREATE_INDEX(index_name =>'Full_Search_IDX' ,tablespace =>'TBLSP_Search_IDX' );
PL/SQL procedure successfully completed
SQL> desc FULL_SEARCH_IDX
Name         Null?    Type             
 -----------  -------- ---------------- 
 METADATA     NOT NULL JSON             
 DATA                  JSON             
 OWNER                 VARCHAR2(128)    
 SOURCE                VARCHAR2(128)    
 KEY                   VARCHAR2(1024)   

نام ایندکس Full_Search_IDX است و از طریق ویوی DBA_JSON_INDEXES می توانیم اطلاعات مربوط به این نوع از ایندکسها را مشاهده کنیم. البته DBA/ALL/USER_INDEXES هم این ایندکس را به عنوان DOMAIN index می شناسد:

SQL> select INDEX_NAME,TABLE_NAME,COLUMN_NAME from DBA_JSON_INDEXES where INDEX_OWNER='USEF';
INDEX_NAME             TABLE_NAME             COLUMN_NAME
---------------------- ---------------------- ------------------------------
FULL_SEARCH_IDX        FULL_SEARCH_IDX        DATA
DR$FULL_SEARCH_IDX$BK  FULL_SEARCH_IDX        METADATA
SQL> select index_name,index_type,table_owner,table_name,ityp_owner,ityp_name from user_indexes where index_name='FULL_SEARCH_IDX';
INDEX_NAME           INDEX_TYPE TABLE_OWNE TABLE_NAME           ITYP_OWNER ITYP_NAME
-------------------- ---------- ---------- -------------------- ---------- --------------------
FULL_SEARCH_IDX      DOMAIN     USEF       FULL_SEARCH_IDX      CTXSYS     CONTEXT_V2

مابه‏ ازای ایندکس ایجاد شده فوق، جدولی هم با همین نام ایجاد می شود بعلاوه 13 جدول دیگر که اسامی همه آنها با $DR شروع می شود:

SQL> select table_name from user_tables where table_name like '%FULL_SEARC%';
TABLE_NAME
----------------------
FULL_SEARCH_IDX
DR$FULL_SEARCH_IDX$B
DR$FULL_SEARCH_IDX$C
DR$FULL_SEARCH_IDX$DG
DR$FULL_SEARCH_IDX$G
DR$FULL_SEARCH_IDX$I
DR$FULL_SEARCH_IDX$K
DR$FULL_SEARCH_IDX$KG
DR$FULL_SEARCH_IDX$N
DR$FULL_SEARCH_IDX$Q
DR$FULL_SEARCH_IDX$SN
DR$FULL_SEARCH_IDX$ST
DR$FULL_SEARCH_IDX$SV
DR$FULL_SEARCH_IDX$U
14 rows selected.

در مرحله بعد باید sourceهای ایندکس را مشخص کنیم source می تواند جدول و یا view باشد. با استفاده از پروسیجر DBMS_SEARCH.ADD_SOURCE می توانیم سورسی را به ایندکس اضافه کنیم:

SQL> exec DBMS_SEARCH.ADD_SOURCE(index_name =>'FULL_SEARCH_IDX' ,source_name => 'IranTBL1' );
PL/SQL procedure successfully completed

توجه! جداول source باید primary key داشته باشند.

بعد از اضافه کردن جدول IranTBL1، محتویات ایندکس را بررسی می کنیم:

SQL>select  owner,source,key,metadata from FULL_SEARCH_IDX;
OWNER SOURCE     KEY        METADATA
----- ---------- ---------- ------------------------------------------------------------
USEF  IRANTBL1   {"ID":1}   {"OWNER":"USEF","SOURCE":"IRANTBL1","KEY":{"ID":1}}

از طریق تابع DBMS_SEARCH.GET_DOCUMENT می توانیم اطلاعات ایندکس شده را هم ببینیم:

SQL> select json_serialize(DBMS_SEARCH.GET_DOCUMENT('FULL_SEARCH_IDX',METADATA)) FULL_SEARCH_IDX from FULL_SEARCH_IDX;
FULL_SEARCH_IDX
--------------------------------------------------------- 
{"USEF":{"IRANTBL1":{"ID":1,"DES":"www.usefzadeh.com"}}}

رکوردهای دیگری هم به جدول source اضافه می کنیم:

SQL> insert into IRANTBL1 values(2,'Ramtollah Rabbani');
1 row created.
SQL> insert into IRANTBL1 values(3,'Armin Bahamin');
1 row created.
SQL> commit;
Commit complete.

بلافاصله دیتای ایندکس هم sync خواهد شد:

SQL> select json_serialize(DBMS_SEARCH.GET_DOCUMENT('FULL_SEARCH_IDX',METADATA)) FULL_SEARCH_IDX from FULL_SEARCH_IDX;

با عبارت contains می توانیم در اطلاعات فوق جستجو انجام دهیم:

SQL> select json_serialize(DBMS_SEARCH.GET_DOCUMENT('FULL_SEARCH_IDX',METADATA)) FULL_SEARCH_IDX from FULL_SEARCH_IDX where contains(data, '%usef%')>0;
FULL_SEARCH_IDX
------------------------------------------------------------
{"USEF":{"IRANTBL1":{"ID":1,"DES":"www.usefzadeh.com"}}}

این جستجو از طریق تابع JSON_TEXTCONTAINS هم قابل انجام است:

SQL> select json_serialize(DBMS_SEARCH.GET_DOCUMENT('FULL_SEARCH_IDX',METADATA)) FULL_SEARCH_IDX from FULL_SEARCH_IDX where json_textcontains(data, '$.USEF.IRANTBL1.DES', '%Ramtollah%');
FULL_SEARCH_IDX
------------------------------------------------------------
{"USEF":{"IRANTBL1":{"ID":2,"DES":"Ramtollah Rabbani"}}}

در ادامه جدول IRANTBL2 را هم به source ایندکس FULL_SEARCH_IDX اضافه می کنیم:

SQL> exec DBMS_SEARCH.ADD_SOURCE(index_name =>'FULL_SEARCH_IDX' ,source_name => 'IranTBL2' );
PL/SQL procedure successfully completed
SQL> select  owner,source,key,metadata from FULL_SEARCH_IDX;
OWNER SOURCE     KEY        METADATA
----- ---------- ---------- ------------------------------------------------------------
USEF  IRANTBL1   {"ID":1}   {"OWNER":"USEF","SOURCE":"IRANTBL1","KEY":{"ID":1}}
USEF  IRANTBL1   {"ID":2}   {"OWNER":"USEF","SOURCE":"IRANTBL1","KEY":{"ID":2}}
USEF  IRANTBL1   {"ID":3}   {"OWNER":"USEF","SOURCE":"IRANTBL1","KEY":{"ID":3}}
USEF  IRANTBL2   {"ID":1}   {"OWNER":"USEF","SOURCE":"IRANTBL2","KEY":{"ID":1}}

با اضافه کردن جدول IranTBL2 به عنوان source دوم، ایندکس FULL_SEARCH_IDX اطلاعات هر دو جدول را نمایش خواهد داد:

SQL> select json_serialize(DBMS_SEARCH.GET_DOCUMENT('FULL_SEARCH_IDX',METADATA)) FULL_SEARCH_IDX from FULL_SEARCH_IDX;
FULL_SEARCH_IDX
----------------------------------------------------------------------------------------------------------------------------------
{"USEF":{"IRANTBL1":{"ID":1,"DES":"www.usefzadeh.com"}}}
{"USEF":{"IRANTBL1":{"ID":2,"DES":"Ramtollah Rabbani"}}}
{"USEF":{"IRANTBL1":{"ID":3,"DES":"Armin Bahamin"}}}
{"USEF":{"IRANTBL2":{"ID":1,"DES1":"My name is Vahid","DES2":"this is a test","DES3":{"name":"vahid","last_name":"usef"}}}}

و جستجو هم می تواند بر روی اطلاعات هر دو جدول انجام شود:

SQL> select json_serialize(DBMS_SEARCH.GET_DOCUMENT('FULL_SEARCH_IDX',METADATA)) FULL_SEARCH_IDX from FULL_SEARCH_IDX where json_textcontains(data, '$.USEF.IRANTBL2.DES3', '%usef%');

SQL> select json_serialize(DBMS_SEARCH.GET_DOCUMENT('FULL_SEARCH_IDX',METADATA)) FULL_SEARCH_IDX from FULL_SEARCH_IDX where contains(data, '%am%')>0;

امکان جستجو به صورت زیر و نمایش خروجی به صورت Relational هم وجود دارد که یکی از کاربردهای مهم آن می تواند جستجو در دیتای با نوع داده LOB باشد:

select b.id,b.des
 from FULL_SEARCH_IDX a, IRANTBL1 b 
where b.id = a.metadata."KEY"."ID" 
  and json_textcontains(data, '$.USEF.IRANTBL1.DES', '%usef%');
   ID DES
----- --------------------
    1 www.usefzadeh.com

برای حذف هر کدام از sourceها می توانیم از تابع DBMS_SEARCH.REMOVE_SOURCE استفاده کنیم:

SQL> exec DBMS_SEARCH.REMOVE_SOURCE(index_name => 'FULL_SEARCH_IDX',source_name =>'IranTBL2');
PL/SQL procedure successfully completed

برای حذف ایندکس هم می توانیم از دستور زیر استفاده کنیم:

SQL> exec DBMS_SEARCH.DROP_INDEX(index_name => 'Full_Search_IDX');
PL/SQL procedure successfully completed

ارائه خدمات مشاوره ، پشتیبانی و نصب و راه اندازی پایگاه داده اوراکل در سراسر کشور...................... تلفن: 09128110897 ایمیل:vahidusefzadeh@gmail.com

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *