测试已测试 | ✓ |
语言语言 | C++C++ |
许可证 | Apache 2 |
发布上次发布 | 2016 年 11 月 |
由 Matt Magoffin、Matt Magoffin、Matt Magoffin 和 wmjesstaylor 维护。
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];
当一次性索引多个文档时,`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
}];
将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”部分的“+”按钮来实现。例如:
接下来,将-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”部分的“+”按钮来实现。例如:
接下来,将-ObjC
添加为其他链接器标志构建设置。
最后,您需要将包含 BRFullTextSearch.xcodeproj 文件的目录路径添加到项目设置中“编译设置”标签页的“头文件搜索路径”中。如果您已将 BRFullTextSearch 作为 git 子模块添加到您的项目中,路径可能类似于 "$(PROJECT_DIR)/../BRFullTextSearch"。