iOS 海量数据本地实时搜索引擎

前言

伴随着业务的迭代, 在数据量有大概四五万情况下, 需要实现实时搜索, 也就是在输入框输入时实时匹配搜索结果, 调用接口不太现实, 所以本地实现实时匹配. 类似于搜索通讯录联系人功能.
数据结构一般是一个很大的数组, 例:

[
  {
    "searchMainCondition": "10A片式保险丝",//搜索条件一
    "searchOtherCondition": "other"//搜索条件二
  },
  {
    "searchMainCondition": "10PK1045皮带",
    "searchOtherCondition": "other"
  },
  {
    "searchMainCondition": "ABS",
    "searchOtherCondition": "other"
  },
  {
    "searchMainCondition": "侧围窗内板(右)",
    "searchOtherCondition": "other"
  }
]

实时搜索的过程可以根据searchMainCondition和searchOtherCondition等等其他条件同时进行模糊匹配

中文转拼音及简单分词

对原始数据做简单的处理, 对searchMainCondition进行全拼转为completeSpellingSearchterm, 由于待搜索completeSpellingSearchterm一般比较短, 只进行加空格达到简单的分词效果. 对searchMainCondition进行简拼转为logogramShorteningSearchterm,这样只需输入 'CWCNB' ---可以搜索到--- '侧围窗内板(右)'

[
  {
    "searchMainCondition": "10A片式保险丝",//搜索条件一
    "searchOtherCondition": "other",//搜索条件二
    "completeSpellingSearchterm": "10APian Shi Bao Xian Si",//转为拼音
    "logogramShorteningSearchterm": ""//汉字首字母
  },
  {
    "searchMainCondition": "10PK1045皮带",
    "searchOtherCondition": "other",
    "completeSpellingSearchterm": "10PK1045Pi Dai",
    "logogramShorteningSearchterm": ""
  },
  {
    "searchMainCondition": "ABS",
    "searchOtherCondition": "other",
    "completeSpellingSearchterm": "ABS",
    "logogramShorteningSearchterm": "ABS"
  },
  {
    "searchMainCondition": "侧围窗内板(右)",
    "searchOtherCondition": "other",
    "completeSpellingSearchterm": "Ce Wei Chuang Nei Ban (You )",
    "logogramShorteningSearchterm": "CWCNB"
  }
]

转化效果图.png

汉字转拼音可以使用该框架中文转拼音, 核心代码块

if ([ChineseInclude isIncludeChineseInString:dic[@"searchMainCondition"]]) {
                        NSString *completeSpellingSearchterm = [PinYinForObjc chineseConvertToPinYin:dic[@"searchMainCondition"]];
                        NSStrin *glogogramShorteningSearchterm = [PinYinForObjc chineseConvertToPinYinHead:dic[@"searchMainCondition"]];
                    }

实时搜索引擎PermissiveResearch

这时用到一个容错模糊搜索引擎PermissiveResearch可以下载修改后的版本PermissiveResearchModified

  1. 导入PermissiveResearchModified类库
  2. PermissiveAlignementMethods.c Identity and Type 更改为Objective-C Source
  3. 设置代理


[[PermissiveResearchDatabase sharedDatabase] setDatasource:self];
[[PermissiveResearchDatabase sharedDatabase] setDelegate:self];
  1. 文本输入发生变化时我们开始实现文本实时检索
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
     [self epcsGetSearchTermString:textField.text];
}
  1. PermissiveResearchDatasource加载搜索源
#pragma mark - PermissiveResearchDatasource

- (void)rebuildDatabase
{
     NSArray *dataArr = [self epcsGetSearchTermDataArr];
     [[PermissiveResearchDatabase sharedDatabase] addObjects:dataArr forKeyPaths:@[@"completeSpellingSearchterm"]];//根据转为拼音后的关键词搜索
}

- (NSArray *)epcsGetSearchTermDataArr
{
     NSArray *sandboxpath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
     NSString *filePath = [[sandboxpath objectAtIndex:0] stringByAppendingPathComponent:@"epcsGetSearchTerm.plist"];
     NSArray *arrMain = [NSArray arrayWithContentsOfFile:filePath];
     return arrMain;
}
  1. PermissiveResearchDelegate
#pragma mark - PermissiveResearchDelegate

-(void)epcsGetSearchTermString:(NSString *)searchedString
{
     searchedKeywordsString = [[NSString alloc] initWithString:searchedString];//缓存中文搜索词
     if ([ChineseInclude isIncludeChineseInString:searchedString]) {
          searchedString = [PinYinForObjc chineseConvertToPinYin:searchedString];
     }
     [[PermissiveResearchDatabase sharedDatabase] searchString:searchedString withOperation:ScoringOperationTypeExact];
}

-(void)searchCompletedWithResults:(NSArray *)results
{
     NSMutableArray *resultArr = @[].mutableCopy;
     if (results && results.count > 0) {
          NSMutableArray *perfectMatchArr = @[].mutableCopy;
          NSMutableArray *prefixArr = @[].mutableCopy;
          NSMutableArray *otherMatchArr = @[].mutableCopy;
          for (int i = 0; i < results.count; i++) {
               id obj = [results objectAtIndex:i];//results为PermissiveObject对象
               if ([obj isKindOfClass:[PermissiveObject class]]) {
                    PermissiveObject *permissiveObj = (PermissiveObject *)obj;
                    NSDictionary *dict = [permissiveObj refencedObject];
                    NSString *dicCurrentSearchterm = dict[@"searchterm"];
                    if ([dicCurrentSearchterm isEqualToString:searchedKeywordsString]) {
                         [perfectMatchArr addSafeObject:dict];//和搜索词完全匹配的
                    } else if ([dicCurrentSearchterm hasPrefix:searchedKeywordsString]) {
                         [prefixArr addSafeObject:dict];//以搜索词开头的
                    } else {
                         [otherMatchArr addSafeObject:dict];
                    }
               }
          }
          //调整搜索结果顺序
          [resultArr addObjectsFromSafeArray:perfectMatchArr];
          [resultArr addObjectsFromSafeArray:prefixArr];
          [resultArr addObjectsFromSafeArray:otherMatchArr];
     }
     matchedSubDataArr = resultArr;
     //刷新数据
}
  1. 清空数据源
- (void)viewDidDisappear:(BOOL)animated
{
     [super viewDidDisappear:animated];
     [[PermissiveResearchDatabase sharedDatabase] removeAllObjects];
}

你可能感兴趣的:(iOS 海量数据本地实时搜索引擎)