table 上的 Oracle 文本索引以及来自另一个 table 的条件数据
Oracle text index on table with conditional data from another table
情况
我正在 Oracle 数据库中存储 版本控制文件。
每个 文件 都有多个 版本 (每个版本都有不同的版本号,随着每个新版本的增加而增加),每个版本都指向一个二进制数据记录,构成文件版本内容
表格(简体):
STORAGE_FILE
- ID NUMBER(19)
STORAGE_FILE_VERSION
- STORAGE_FILE_ID NUMBER(19) -> references STORAGE_FILE(ID)
- DATA_ID NUMBER(19) -> references BINARY_DATA(ID)
BINARY_DATA
- ID NUMBER(19)
- DATA BLOB
问题
要在文件内搜索,我想创建一个 Oracle 文本索引,但仅在每个文件 的最新版本上。
索引应属于 STORAGE_FILE
,包含来自 STORAGE_FILE_VERSION
的索引引用 BINARY_DATA.data
和最新(最大)版本。
使用以下查询(我还为此创建了一个视图),我可以确定每个文件的最新版本和数据:
select latest_file_version.ID, latest_file_version.VERSION, b.data from (
select f.ID, max(v.VERSION) as version from STORAGE_FILE f
join STORAGE_FILE_VERSION v on v.STORAGE_FILE_ID = f.ID
group by f.ID
) latest_file_version
join STORAGE_FILE_VERSION v
on v.STORAGE_FILE_ID = latest_file_version.ID and v.VERSION = latest_file_version.VERSION
join BINARY_DATA b on b.ID = v.DATA_ID
Oracle 为文本索引提供了几种 datastore types,但我不确定哪一种适合我的情况:
- USER_DATASTORE 允许使用用户定义的存储过程为索引提供内容,这(我想)会起作用,但似乎有点矫枉过正,如果可以避免,我宁愿避免添加存储过程。
- DETAIL_DATASTORE 允许索引列和数据列位于不同的表上。我不清楚我是否可以以某种方式使用这种机制来间接索引最新版本的二进制数据。
其他数据存储似乎也不适合这个问题。
关于如何在不 回退到物化视图的情况下实现这样的索引的任何建议?
USER_DATASTORE
的解决方案非常有效:
首先,我们需要 STORAGE_FILE
上的 索引列 (标记要索引的记录,以及针对它的 运行 Oracle 文本查询):
alter table STORAGE_FILE add INDEX_FLAG char(1) default 'Y';
需要一个过程来为索引提供blob。在这里,我们要使用视图(有问题的查询)来确定最新的文件版本:
create or replace procedure STORAGE_FILE_DATA
(rid in rowid, tlob in out NOCOPY blob ) is
begin
begin
select data.binary_data into tlob from STORAGE_FILE f
left outer join VW_STORAGE_FILE_DATA data on f.id=data.file_id
where f.rowid = rid and f.INDEX_FLAG='Y';
exception
when NO_DATA_FOUND then tlob := null;
end;
end;
/
接下来,我们使用上述过程创建 index(和 preferences):
begin
ctx_ddl.create_preference('FILE_DATA_DATASTORE','user_datastore');
ctx_ddl.set_attribute('FILE_DATA_DATASTORE','procedure','STORAGE_FILE_DATA');
ctx_ddl.set_attribute('FILE_DATA_DATASTORE','output_type','blob_loc');
end;
/
create index INDEX_FILE_DATA
on STORAGE_FILE (INDEX_FLAG)
indextype is ctxsys.context
parameters ('filter ctxsys.auto_filter
datastore FILE_DATA_DATASTORE
memory 200M
transactional')
/
此外,我们需要一个 触发器 来标记条目,以便在更改后重新编制索引:
create or replace trigger TRIGGER_INDEX_FILE
before update on STORAGE_FILE
for each row
begin
:new.INDEX_FLAG := 'Y';
end;
/
我们完成了。现在我们可以 运行 仅对最新文件版本的数据进行全文查询:
select * from STORAGE_FILE f
where contains (f.INDEX_FLAG, 'Hello AND World', 1) > 0;
情况
我正在 Oracle 数据库中存储 版本控制文件。 每个 文件 都有多个 版本 (每个版本都有不同的版本号,随着每个新版本的增加而增加),每个版本都指向一个二进制数据记录,构成文件版本内容
表格(简体):
STORAGE_FILE
- ID NUMBER(19)
STORAGE_FILE_VERSION
- STORAGE_FILE_ID NUMBER(19) -> references STORAGE_FILE(ID)
- DATA_ID NUMBER(19) -> references BINARY_DATA(ID)
BINARY_DATA
- ID NUMBER(19)
- DATA BLOB
问题
要在文件内搜索,我想创建一个 Oracle 文本索引,但仅在每个文件 的最新版本上。
索引应属于 STORAGE_FILE
,包含来自 STORAGE_FILE_VERSION
的索引引用 BINARY_DATA.data
和最新(最大)版本。
使用以下查询(我还为此创建了一个视图),我可以确定每个文件的最新版本和数据:
select latest_file_version.ID, latest_file_version.VERSION, b.data from (
select f.ID, max(v.VERSION) as version from STORAGE_FILE f
join STORAGE_FILE_VERSION v on v.STORAGE_FILE_ID = f.ID
group by f.ID
) latest_file_version
join STORAGE_FILE_VERSION v
on v.STORAGE_FILE_ID = latest_file_version.ID and v.VERSION = latest_file_version.VERSION
join BINARY_DATA b on b.ID = v.DATA_ID
Oracle 为文本索引提供了几种 datastore types,但我不确定哪一种适合我的情况:
- USER_DATASTORE 允许使用用户定义的存储过程为索引提供内容,这(我想)会起作用,但似乎有点矫枉过正,如果可以避免,我宁愿避免添加存储过程。
- DETAIL_DATASTORE 允许索引列和数据列位于不同的表上。我不清楚我是否可以以某种方式使用这种机制来间接索引最新版本的二进制数据。
其他数据存储似乎也不适合这个问题。
关于如何在不 回退到物化视图的情况下实现这样的索引的任何建议?
USER_DATASTORE
的解决方案非常有效:
首先,我们需要 STORAGE_FILE
上的 索引列 (标记要索引的记录,以及针对它的 运行 Oracle 文本查询):
alter table STORAGE_FILE add INDEX_FLAG char(1) default 'Y';
需要一个过程来为索引提供blob。在这里,我们要使用视图(有问题的查询)来确定最新的文件版本:
create or replace procedure STORAGE_FILE_DATA
(rid in rowid, tlob in out NOCOPY blob ) is
begin
begin
select data.binary_data into tlob from STORAGE_FILE f
left outer join VW_STORAGE_FILE_DATA data on f.id=data.file_id
where f.rowid = rid and f.INDEX_FLAG='Y';
exception
when NO_DATA_FOUND then tlob := null;
end;
end;
/
接下来,我们使用上述过程创建 index(和 preferences):
begin
ctx_ddl.create_preference('FILE_DATA_DATASTORE','user_datastore');
ctx_ddl.set_attribute('FILE_DATA_DATASTORE','procedure','STORAGE_FILE_DATA');
ctx_ddl.set_attribute('FILE_DATA_DATASTORE','output_type','blob_loc');
end;
/
create index INDEX_FILE_DATA
on STORAGE_FILE (INDEX_FLAG)
indextype is ctxsys.context
parameters ('filter ctxsys.auto_filter
datastore FILE_DATA_DATASTORE
memory 200M
transactional')
/
此外,我们需要一个 触发器 来标记条目,以便在更改后重新编制索引:
create or replace trigger TRIGGER_INDEX_FILE
before update on STORAGE_FILE
for each row
begin
:new.INDEX_FLAG := 'Y';
end;
/
我们完成了。现在我们可以 运行 仅对最新文件版本的数据进行全文查询:
select * from STORAGE_FILE f
where contains (f.INDEX_FLAG, 'Hello AND World', 1) > 0;