全文检索 (Full Text Search)
文本搜索(TextSearch)面向已打开的单个 PDF 文档做页内或页范围匹配。
全文检索(FullTextSearch,命名空间 foxit::fts)面向目录下多个 PDF 文件:先建立或更新索引数据库,再按关键词检索,并通过回调返回命中结果。
系统要求
- 授权许可:需要包含
Standard模块的授权码 - 开发语言:C、C++、Java、C#、Python、Objective-C、Node.js、Go
能力概览
全文检索的典型能力包括:
- 为指定目录(含子目录)中的 PDF 建立或更新索引(
StartUpdateIndex/UpdateIndexWithFilePath) - 按关键词在已索引文件中检索(
SearchOf),并通过SearchCallback接收命中信息 - 检索时忽略模式串字符间空白(
SetIgnoreSpace) - 检索过程中协作取消(
SearchCallback::NeedToCancel)
其中,忽略空白与协作取消从 12.0 版本开始提供。完整可运行示例见产品包 examples/simple_demo/fulltextsearch。
基本流程
- 构造
FullTextSearch,可选调用SetDataBasePath指定索引库路径(首次建索前有效;未设置时默认可为应用旁fts.db)。 - 用
DocumentsSource指定待索引目录,调用StartUpdateIndex(渐进式)或对单文件调用UpdateIndexWithFilePath。 - 实现
SearchCallback:在RetrieveSearchResult中处理命中,并实现NeedToCancel。 - 按需调用
SetIgnoreSpace,再调用SearchOf执行检索。
忽略模式串空白
从 12.0 版本开始,可通过 FullTextSearch::SetIgnoreSpace 控制匹配时是否忽略模式串字符之间的空白(空格、制表符、换行等)。默认关闭;开启后立即生效,无需重建索引,且不改变已建索引内容。
c++
full_text_search.SetIgnoreSpace(true); // 默认 false
java
search.setIgnoreSpace(true); // 默认 false
csharp
full_text_search.SetIgnoreSpace(true); // 默认 false
py
full_text_search.SetIgnoreSpace(True) # 默认 False
js
full_text_search.SetIgnoreSpace(true); // 默认 false
go
fullTextSearch.SetIgnoreSpace(true) // 默认 false
检索取消
从 12.0 版本开始,SearchCallback 提供 NeedToCancel,供宿主在检索过程中请求取消:返回 true 表示取消,返回 false 表示继续。旧版本没有该方法;已自定义回调的工程必须补上实现,否则无法编译或无法加载。不需要取消时返回“继续”。
| 语言 | 12.0 起需实现 |
|---|---|
| C++ | virtual bool NeedToCancel() = 0; |
| C | FS_BOOL (*NeedToCancel)(void* user_data); |
| Java | boolean needToCancel() |
| C# | override bool NeedToCancel() |
| Python | def NeedToCancel(self, *args) |
| Node.js | NeedToCancel() |
| Go | func (cb ...) NeedToCancel() bool |
| Objective-C | -(BOOL)needToCancel |
以下示例演示:建索 →(可选)忽略空白 → 检索,并实现 NeedToCancel。完整可运行示例见产品包 examples/simple_demo/fulltextsearch。
c++
#include "include/common/fs_common.h"
#include "include/fts/fs_fulltextsearch.h"
using namespace foxit;
using namespace foxit::common;
using namespace foxit::fts;
class SearchCallbackImp : public SearchCallback {
public:
virtual void Release() override { delete this; }
virtual bool NeedToCancel() override { return false; }
virtual int RetrieveSearchResult(const wchar_t* file_path, int page_index,
const WString& match_result,
int match_start_text_index, int match_end_text_index,
const WString& sentence,
int sentence_start_text_index,
int sentence_end_text_index) override {
// 处理命中结果。
return 0;
}
};
// 假设已 Library::Initialize。
FullTextSearch full_text_search;
full_text_search.SetDataBasePath("./search.db");
DocumentsSource docs_source("./pdf_folder");
Progressive search_progress = full_text_search.StartUpdateIndex(docs_source, NULL, false);
int state = Progressive::e_ToBeContinued;
while (state == Progressive::e_ToBeContinued) {
state = search_progress.Continue();
}
full_text_search.SetIgnoreSpace(true);
SearchCallbackImp* search_callback = new SearchCallbackImp();
full_text_search.SearchOf("Foxit", FullTextSearch::e_RankHitCountASC, search_callback);
C
#include "include/fs_basictypes_c.h"
#include "include/fs_common_c.h"
#include "include/fs_fulltextsearch_c.h"
...
FS_BOOL gNeedToCancel(void* user_data) {
return FALSE; // 不需要取消时返回 FALSE
}
int gRetrieveSearchResult(void* user_data, const wchar_t* file_path, int page_index,
const wchar_t* match_result, int match_start_text_index,
int match_end_text_index, const wchar_t* sentence,
int sentence_start_text_index, int sentence_end_text_index) {
// 处理命中结果。
return 0;
}
// 假设已 FSDK_Library_Initialize。
FS_FULLTEXTSEARCH_HANDLE full_text_search = NULL;
FSDK_FullTextSearch_Create(&full_text_search);
FSDK_FullTextSearch_SetDataBasePath(full_text_search, "./search.db");
FS_DOCUMENTSSOURCE_HANDLE docs_source = NULL;
FSDK_DocumentsSource_Create("./pdf_folder", &docs_source);
FS_PROGRESSIVE_HANDLE search_progress = NULL;
FS_PROGRESSIVESTATE state = e_FSToBeContinued;
FSDK_FullTextSearch_StartUpdateIndex(full_text_search, docs_source, NULL, FALSE, &search_progress);
while (state == e_FSToBeContinued) {
FSDK_Progressive_Continue(search_progress, &state);
}
FSSearchCallback* search_callback = (FSSearchCallback*)malloc(sizeof(FSSearchCallback));
search_callback->user_data = search_callback;
search_callback->Release = gRelease;
search_callback->RetrieveSearchResult = gRetrieveSearchResult;
search_callback->NeedToCancel = gNeedToCancel;
FS_BOOL return_value = FALSE;
FSDK_FullTextSearch_SearchOf(full_text_search, "Foxit", e_FSRankHitCountASC, search_callback, &return_value);
java
import com.foxit.sdk.common.*;
import com.foxit.sdk.fts.*;
class MySearchCallback extends SearchCallback {
@Override
public void release() {}
@Override
public boolean needToCancel() {
return false; // 不需要取消时返回 false
}
@Override
public int retrieveSearchResult(String filePath, int pageIndex, String matchResult,
int matchStartTextIndex, int matchEndTextIndex,
String sentence, int sentenceStartTextIndex,
int sentenceEndTextIndex) {
// 处理命中结果。
return 0;
}
}
// 假设已 Library.initialize。
FullTextSearch search = new FullTextSearch();
search.setDataBasePath("./search.db");
DocumentsSource source = new DocumentsSource("./pdf_folder");
Progressive progressive = search.startUpdateIndex(source, null, false);
int state = Progressive.e_ToBeContinued;
while (state == Progressive.e_ToBeContinued) {
state = progressive.resume();
}
search.setIgnoreSpace(true);
MySearchCallback searchCallback = new MySearchCallback();
search.searchOf("Foxit", FullTextSearch.e_RankHitCountASC, searchCallback);
csharp
using foxit.common;
using foxit.fts;
public class SearchCallbackImp : SearchCallback
{
public override void Release() {}
public override bool NeedToCancel()
{
return false; // 不需要取消时返回 false
}
public override int RetrieveSearchResult(string file_path, int page_index, string match_result,
int match_start_text_index, int match_end_text_index, string sentence,
int sentence_start_text_index, int sentence_end_text_index)
{
// 处理命中结果。
return 0;
}
}
// 假设已 Library.Initialize。
using (FullTextSearch full_text_search = new FullTextSearch())
{
full_text_search.SetDataBasePath("./search.db");
using (DocumentsSource docs_source = new DocumentsSource("./pdf_folder"))
{
Progressive search_progress = full_text_search.StartUpdateIndex(docs_source, null, false);
Progressive.State state = Progressive.State.e_ToBeContinued;
while (state == Progressive.State.e_ToBeContinued)
{
state = search_progress.Continue();
}
full_text_search.SetIgnoreSpace(true);
using (SearchCallbackImp searchCallback = new SearchCallbackImp())
{
full_text_search.SearchOf("Foxit", FullTextSearch.RankMode.e_RankHitCountASC, searchCallback);
}
}
}
py
from FoxitPDFSDKPython3 import *
class SearchCallbackImp(SearchCallback):
def Release(self, *args):
pass
def NeedToCancel(self, *args):
return False # 不需要取消时返回 False
def RetrieveSearchResult(self, *args):
# 处理命中结果。
return 0
# 假设已 Library.Initialize。
full_text_search = FullTextSearch()
full_text_search.SetDataBasePath("./search.db")
docs_source = DocumentsSource("./pdf_folder")
search_progress = full_text_search.StartUpdateIndex(docs_source, None, False)
state = Progressive.e_ToBeContinued
while state == Progressive.e_ToBeContinued:
state = search_progress.Continue()
full_text_search.SetIgnoreSpace(True)
searchCallback = SearchCallbackImp()
full_text_search.SearchOf("Foxit", FullTextSearch.e_RankHitCountASC, searchCallback)
objc
@interface MySearchCallback : NSObject<FSSearchCallback>
@end
@implementation MySearchCallback
-(BOOL)needToCancel {
return NO; // 不需要取消时返回 NO
}
-(int)retrieveSearchResult:(NSString *)file_path page_index:(int)page_index
match_result:(NSString *)match_result
match_start_text_index:(int)match_start_text_index
match_end_text_index:(int)match_end_text_index
sentence:(NSString *)sentence
match_sentence_start_text_index:(int)match_sentence_start_text_index
match_sentence_end_text_index:(int)match_sentence_end_text_index {
// 处理命中结果。
return 0;
}
@end
// 假设已 [FSLibrary initialize:sn key:key]。
FSFullTextSearch* fulltextsearch = [[FSFullTextSearch alloc] init];
[fulltextsearch setDataBasePath:@"./search.db"];
FSDocumentsSource* docs_source = [[FSDocumentsSource alloc] initWithDirectory:@"./pdf_folder"];
FSProgressive* search_progress = [fulltextsearch startUpdateIndex:docs_source pause:nil reupdate:NO];
FSProgressiveState state = FSProgressiveStateToBeContinued;
while (state == FSProgressiveStateToBeContinued) {
state = [search_progress continue];
}
MySearchCallback* searchCallback = [[MySearchCallback alloc] init];
[fulltextsearch searchOf:@"Foxit" rank_mode:FSFullTextSearchRankHitCountASC callback:searchCallback];
js
const FSDK = require("@fuxinsoft/fuxin-pdf-sdk-node");
class SearchCallbackImp {
Release() {}
NeedToCancel() {
return false; // 不需要取消时返回 false
}
RetrieveSearchResult(filePath, pageIndex, matchResult, matchStartTextIndex,
matchEndTextIndex, sentence, sentenceStartTextIndex,
sentenceEndTextIndex) {
// 处理命中结果。
return 0;
}
}
// 假设已 FSDK.Library.Initialize。
let full_text_search = new FSDK.FullTextSearch();
full_text_search.SetDataBasePath("./search.db");
let docs_source = new FSDK.DocumentsSource("./pdf_folder");
let search_progress = full_text_search.StartUpdateIndex(docs_source, null, false);
let state = FSDK.Progressive.e_ToBeContinued;
while (state == FSDK.Progressive.e_ToBeContinued) {
state = search_progress.Continue();
}
full_text_search.SetIgnoreSpace(true);
let callback = new SearchCallbackImp();
let search_callback = new FSDK.SearchCallback(callback);
full_text_search.SearchOf("Foxit", FSDK.FullTextSearch.e_RankHitCountASC, search_callback);
go
type SearchCallbackImp struct {
fsdk.SearchCallback
}
func (cb SearchCallbackImp) Release() {}
func (cb SearchCallbackImp) NeedToCancel() bool {
return false // 不需要取消时返回 false
}
func (cb SearchCallbackImp) RetrieveSearchResult(filePath string, pageIndex int, matchResult string,
matchStartTextIndex, matchEndTextIndex int, sentence string,
sentenceStartTextIndex, sentenceEndTextIndex int) int {
// 处理命中结果。
return 0
}
// 假设已 fsdk.LibraryInitialize。
fullTextSearch := fsdk.NewFullTextSearch()
defer fsdk.DeleteFullTextSearch(fullTextSearch)
fullTextSearch.SetDataBasePath("./search.db")
docsSource := fsdk.NewDocumentsSource("./pdf_folder")
defer fsdk.DeleteDocumentsSource(docsSource)
searchProgress := fullTextSearch.StartUpdateIndex(docsSource, nil, false)
state := fsdk.ProgressiveE_ToBeContinued
for state == fsdk.ProgressiveE_ToBeContinued {
state = searchProgress.Continue()
}
fullTextSearch.SetIgnoreSpace(true)
searchCallback := SearchCallbackImp{}
searchCallback_ := fsdk.NewDirectorSearchCallback(searchCallback)
fullTextSearch.SearchOf("Foxit", fsdk.FullTextSearchE_RankHitCountASC, searchCallback_)
若业务在旧版本已自定义 SearchCallback 子类,升级到 12.0 及更高版本时的编译与实现要求,请参阅上文 检索取消 中的签名表。