You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle 19c中如何找出未被Oracle Text索引的文档

环境:Oracle 19c

我们的系统使用Oracle Text(Oracle 19c)对存储为BFILE的PDF文件建立索引。此前通过Adobe Acrobat对PDF进行OCR预处理,但约一年前发现OCR偶尔会将页面旋转90或180度,这是可复现的Adobe Bug。因此告知客户需自行OCR后再上传,并停用了自身的OCR流程。
目前正调整OCR处理流程,需要找出所有在Oracle Text索引中无任何Token(词汇)的文档以重新处理,推测这些文档可能未被客户OCR,无法通过Oracle Text检索。

问题

  1. 如何查询Oracle Text找出无索引Token的文档?
  2. 是否有方法检测PDF文档是否已被OCR?

示例表脚本

CREATE TABLE MY_SCHEMA.ORADOCS
(
  DOC_ID            NUMBER                      NOT NULL GENERATED BY DEFAULT ON NULL AS IDENTITY,
  SUBJECT_OR_TITLE  VARCHAR2(255 BYTE)          NOT NULL,
  DOC_DT            DATE                        NOT NULL,
  AUTHOR            VARCHAR2(255 BYTE),
  CREATE_DT         DATE                        DEFAULT sysdate               NOT NULL,
  CREATE_USER       VARCHAR2(100 BYTE)          DEFAULT USER                  NOT NULL,
  ORIG_FILENAME     VARCHAR2(255 BYTE),
  ORADOC_FILE       BFILE
)
TABLESPACE MY_DOC;

ALTER TABLE MY_SCHEMA.ORADOCS ADD (
  CONSTRAINT ORADOCS_PK1
  PRIMARY KEY
  (DOC_ID)
  USING INDEX MY_SCHEMA.ORADOCS_PK1
  ENABLE VALIDATE);

CREATE INDEX MY_SCHEMA.AUTHOR_ORADOCS ON MY_SCHEMA.ORADOCS
(AUTHOR)
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS('storage meta_storage  memory 4G SYNC(ON COMMIT)');

CREATE INDEX MY_SCHEMA.ORADOC_FILE ON MY_SCHEMA.ORADOCS
(ORADOC_FILE)
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS('storage meta_storage memory 6G SYNC(ON COMMIT)');

CREATE INDEX MY_SCHEMA.SUBJECT_ORADOCS ON MY_SCHEMA.ORADOCS
(SUBJECT_OR_TITLE)
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS('storage meta_storage  memory 4G SYNC(ON COMMIT)');

解决方案

问题1:找出Oracle Text索引中无Token的文档

以下两种方法可直接查询无索引Token的文档:

方法1:通过系统视图对比

利用CTX_USER_DOCUMENTS视图获取已生成索引Token的文档ID,再与原表左连接筛选出无匹配的记录:

SELECT d.DOC_ID, d.ORIG_FILENAME
FROM MY_SCHEMA.ORADOCS d
LEFT JOIN (
    SELECT DOCID
    FROM CTX_USER_DOCUMENTS
    WHERE INDEX_NAME = 'ORADOC_FILE' -- 指定BFILE字段对应的索引名
) idx ON d.DOC_ID = idx.DOCID
WHERE idx.DOCID IS NULL;

注:需确保索引创建时未指定自定义DOCID参数,否则CTX_USER_DOCUMENTS中的DOCID可能与表主键不匹配。

方法2:用CTX_DOC包验证单文档

若需逐个验证文档是否存在Token,可调用CTX_DOC.TOKEN_TYPE函数统计Token数量:

DECLARE
  v_token_count NUMBER;
BEGIN
  SELECT COUNT(*) INTO v_token_count
  FROM TABLE(CTX_DOC.TOKEN_TYPE('MY_SCHEMA.ORADOC_FILE', :input_doc_id));
  
  IF v_token_count = 0 THEN
    DBMS_OUTPUT.PUT_LINE('文档' || :input_doc_id || '无有效索引Token');
  END IF;
END;
/

问题2:检测PDF是否已被OCR

可通过Oracle内部逻辑或外部工具两种方式检测:

方式1:Oracle内部读取PDF属性

经过OCR的PDF会包含可提取的文本流,读取BFILE的前部分内容,检查是否存在PDF文本相关标记:

DECLARE
  v_target_file BFILE;
  v_content_buffer VARCHAR2(32767);
  v_has_text BOOLEAN := FALSE;
BEGIN
  SELECT ORADOC_FILE INTO v_target_file FROM MY_SCHEMA.ORADOCS WHERE DOC_ID = :input_doc_id;
  
  DBMS_LOB.OPEN(v_target_file, DBMS_LOB.LOB_READONLY);
  DBMS_LOB.READ(v_target_file, 32767, 1, v_content_buffer);
  
  -- 检查PDF文本相关对象标记
  IF INSTR(v_content_buffer, '/Contents') > 0 OR INSTR(v_content_buffer, '/Font') > 0 THEN
    v_has_text := TRUE;
  END IF;
  
  DBMS_LOB.CLOSE(v_target_file);
  
  IF v_has_text THEN
    DBMS_OUTPUT.PUT_LINE('该PDF包含可提取文本,大概率已完成OCR');
  ELSE
    DBMS_OUTPUT.PUT_LINE('该PDF无文本内容,未经过OCR');
  END IF;
END;
/

注:部分扫描件PDF可能包含少量元数据文本,需结合实际场景调整判断逻辑。

方式2:外部工具提取验证

在服务器安装poppler-utils工具包,使用pdftotext提取PDF文本,通过判断提取内容的长度来确认:

pdftotext target_file.pdf - | wc -c

若输出为0或极小值(仅包含元数据),则文档未经过OCR处理。

内容的提问来源于stack exchange,提问作者Richard Anderson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 21:13:29