BRFullTextSearch 2.0.0-beta1

BRFullTextSearch 2.0.0-beta1

测试已测试
语言语言 C++C++
许可证 Apache 2
发布上次发布2016 年 11 月

Matt MagoffinMatt MagoffinMatt Magoffinwmjesstaylor 维护。



BRFullTextSearch 2.0.0-beta1

  • 作者:
  • Matt Magoffin

Objective-C 全文搜索引擎。

该项目为一个集成到 iOS 或 OS X 项目的全文搜索功能提供了一种方法。首先,它提供了一个基于协议的 API,用于简单的文本索引和搜索框架。其次,它提供了基于 CLucene 的该框架的实现。

示例用法

以下片段显示了 API 的工作原理。`CLuceneSearchService` 引用是代码中唯一与 CLucene 相关的部分

id<BRSearchService> service = [[CLuceneSearchService alloc] initWithIndexPath:@"/some/path"];

// add a document to the index
id<BRIndexable> doc = [[BRSimpleIndexable alloc] initWithIdentifier:@"1" data:@{
                       kBRSearchFieldNameTitle : @"Special document",
                       kBRSearchFieldNameValue : @"This is a long winded note with really important details in it."
                       }];
NSError *error = nil;
[service addObjectToIndexAndWait:doc error:&error];

// search for documents and log contents of each result
id<BRSearchResults> results = [service search:@"special"];
[results iterateWithBlock:^(NSUInteger index, id<BRSearchResult>result, BOOL *stop) {
    NSLog(@"Found result: %@", [result dictionaryRepresentation]);
}];

示例项目

源代码中包含了一些示例项目

谓词查询

`BRSearchService` API 支持 `NSPredicate` 基于的查询

- (id<BRSearchResults>)searchWithPredicate:(NSPredicate *)predicate
                                    sortBy:(NSString *)sortFieldName
                                  sortType:(BRSearchSortType)sortType
                                 ascending:(BOOL)ascending;

当从用户提供的查询文本构造查询时,这种方法非常有用。例如,您可以支持基于前缀的查询(例如,搜索 ca* 以匹配 cat

// get query as string, from text field for Example
NSString * query = ...;

static NSExpression *ValueExpression;
if ( ValueExpression == nil ) {
    ValueExpression = [NSExpression expressionForKeyPath:kBRSearchFieldNameValue];
}
NSArray *tokens = [[query stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]
                   componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:([tokens count] * 2)];
for ( NSString *token in tokens ) {
    [predicates addObject:[NSComparisonPredicate predicateWithLeftExpression:ValueExpression
                                                             rightExpression:[NSExpression expressionForConstantValue:token]
                                                                    modifier:NSDirectPredicateModifier
                                                                        type:NSLikePredicateOperatorType
                                                                     options:0]];
    [predicates addObject:[NSComparisonPredicate predicateWithLeftExpression:ValueExpression
                                                             rightExpression:[NSExpression expressionForConstantValue:token]
                                                                    modifier:NSDirectPredicateModifier
                                                                        type:NSBeginsWithPredicateOperatorType
                                                                     options:0]];
}
NSPredicate *predicateQuery = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
searchResults = [searchService searchWithPredicate:predicateQuery sortBy:nil sortType:0 ascending:NO];

批量 API

当一次性索引多个文档时,`BRSearchService` 提供了一组专为高效大量操作设计的特定方法

// bulk block callback function.
typedef void (^BRSearchServiceIndexUpdateBlock)(id <BRIndexUpdateContext> updateContext);

// perform a bulk operation, calling the passed on block
- (void)bulkUpdateIndex:(BRSearchServiceIndexUpdateBlock)updateBlock
                  queue:(dispatch_queue_t)finishedQueue
               finished:(BRSearchServiceUpdateCallbackBlock)finished;

// from within the block, the following methods can be used (notice the updateContext parameter):

- (void)addObjectToIndex:(id <BRIndexable> )object context:(id <BRIndexUpdateContext> )updateContext;

- (int)removeObjectFromIndex:(BRSearchObjectType)type withIdentifier:(NSString *)identifier
                     context:(id <BRIndexUpdateContext> )updateContext;

- (int)removeObjectsFromIndexMatchingPredicate:(NSPredicate *)predicate
                                       context:(id <BRIndexUpdateContext> )updateContext;

- (int)removeAllObjectsFromIndex:(id <BRIndexUpdateContext> )updateContext;

以下是一个批量操作示例,将 100,000 个文档添加到索引中;注意在操作期间使用 `@autoreleasepool` 限制了内存使用

id<BRSearchService> service = ...;
[service bulkUpdateIndex:^(id<BRIndexUpdateContext> updateContext) {

    if ( [updateContext respondsToSelector:@selector(setOptimizeWhenDone:)] ) {
        updateContext.optimizeWhenDone = YES;
    }

    // add a bunch of documents to the index, in small autorelease batches
    for ( int i = 0; i < 100000; i+= 1000 ) {
        @autoreleasepool {
            for ( int j = 0; j < 1000; j++ ) {
                id<BRIndexable> doc = ...;
                [service addObjectToIndex:doc context:updateContext];
            }
        }
    }

} queue:dispatch_get_main_queue() finished:^(int updateCount, NSError *error) {
    // all finished here
}];

Core Data 支持

将BRFullTextSearch集成到Core Data非常简单,可以在Core Data变化持久化的同时维护搜索索引。一种方法是监听NSManagedObjectContextDidSaveNotification通知,并将Core Data变化作为索引删除和更新操作处理。SampleCoreDataProject iOS项目包含了这个集成的示例。该应用程序允许您创建小型的粘性笔记并搜索这些笔记的文本。请查看示例项目中的CoreDataManager类,其maintainSearchIndexFromManagedObjectDidSave:方法处理这些操作。

SampleOSXCocoaPodsProject OS X项目也包含了这个集成的示例。有关详细信息,请参阅该项目中的CoreDataManager类。

项目集成

您可以通过CocoaPods或手动将其作为依赖项目或静态库进行集成。

通过静态库

使用这种方法,您将构建一个静态库框架,您可以手动将其集成到自己的项目中。在克隆BRFullTextSearch存储库后,首先初始化git子模块。例如

git clone https://github.com/Blue-Rocket/BRFullTextSearch.git
cd BRFullTextSearch
git submodule update --init

这将拉取相关子模块,例如CLucene。

BRFullTextSearch的Xcode项目包括一个名为BRFullTextSearch.framework的目标,它构建一个静态库框架。构建该目标,将在根项目目录中产生一个Framework/Release/BRFullTextSearch.framework捆绑包。将该框架复制到您的项目中,并添加为构建依赖项。

您还必须添加以下链接器构建依赖项,您可以通过点击项目设置中“构建阶段”标签下的“Link Binary With Libraries”部分的“+”按钮来实现。例如:

  • libz
  • libstdc++

接下来,将-ObjC添加为其他链接器标志构建设置。如果您项目中没有C++源代码,您可能还需要将-stdlib=libstdc++添加到这个设置中。

最后,您需要将包含BRFullTextSearch.framework捆绑包的目录路径添加到项目设置的“构建设置”标签下的框架搜索路径值。

此存储库中包含的SampleStaticLibraryProject是一个示例项目,使用静态库框架集成方法设置。您必须首先构建BRFullTextSearch.framework,然后打开此项目。运行该项目时,它将使用一些拉丁文本对一组文档进行索引。然后,您可以使用简单的用户界面搜索拉丁单词。

通过依赖项目

将BRFullTextSearch集成到项目中另一种方法是,将BRFullTextSearch Xcode项目添加为您的项目的依赖项目。BRFullTextSearch Xcode项目包括一个名为BRFullTextSearch的目标,它构建一个静态库。您可以使用该目标作为自己的项目的依赖项。

在克隆BRFullTextSearch存储库后,首先初始化git子模块。例如

git clone https://github.com/Blue-Rocket/BRFullTextSearch.git
cd BRFullTextSearch
git submodule update --init

这将拉取相关子模块,例如CLucene。

然后将BRFullTextSearch.xcodeproj拖到项目导航器中的您的项目中。然后转到项目设置的“构建阶段”标签。展开“目标依赖项”部分,并点击“+”按钮。您应该看到Available Options中的“BRFullTextSearch”静态库目标。选择它,然后点击“Add”按钮。

您还必须添加以下链接器构建依赖项,您可以通过点击项目设置中“构建阶段”标签下的“Link Binary With Libraries”部分的“+”按钮来实现。例如:

  • libz
  • libstdc++

接下来,将-ObjC添加为其他链接器标志构建设置。

最后,您需要将包含 BRFullTextSearch.xcodeproj 文件的目录路径添加到项目设置中“编译设置”标签页的“头文件搜索路径”中。如果您已将 BRFullTextSearch 作为 git 子模块添加到您的项目中,路径可能类似于 "$(PROJECT_DIR)/../BRFullTextSearch"