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 的解决方案非常有效:

首先,我们需要 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;