转:十五分钟介绍 Redis 数据结构
星期二, 十一月 1st, 2011http://www.oschina.net/question/54100_28977
http://www.oschina.net/question/54100_28977
以前装过一次sphinx,现在有了中文站coreseek,他们整合了中文分词,相对来说还是方便了不少,coreseek的包里除了sphinx以外还有mmseg和一个用于测试的代码包,安装还算顺利。
安装文档见这里
http://www.coreseek.cn/products-install/install_on_bsd_linux/
在安装sphinx php扩展的时候略微麻烦了一下,直接用pecl install sphinx不成功,说找不到libsphinxclient库,后来发现libsphinxclient就在coreseek-4.1-beta/testpack/api/libsphinxclient路径下,安装之。
然后还是不能用pecl方式安装,在这里 http://pecl.php.net/package/sphinx 下载了安装包,用phpize方式安装ok。
如不安装php扩展,在testpack目录里也有一php版本的sphinx class可以使用。
对于mysql的应用,先按提示修改好csft_mysql.conf里的相关参数
然后建索引
/usr/local/coreseek/bin/indexer -c etc/csft_mysql.conf –all
如果服务器已经启动,建索引是不能覆盖的,需要加入–rotate参数
/usr/local/coreseek/bin/indexer -c etc/csft_mysql.conf –all –rotate
启动服务
/usr/local/coreseek/bin/searchd -c etc/csft_mysql.conf
停止服务
/usr/local/coreseek/bin/searchd -c etc/csft_mysql.conf –stop
启动服务后,可用php进行查询。。
1 2 3 4 5 6 7 8 9 10 11 |
另外还有一些高级用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | //注意文件的编码格式需要保存为为UTF-8格式 require ( "sphinxapi.php" ); $cl = new SphinxClient (); $cl->SetServer ( '127.0.0.1', 9312); //以下设置用于返回数组形式的结果 $cl->SetArrayResult ( true ); /* //ID的过滤 $cl->SetIDRange(3,4); //sql_attr_uint等类型的属性字段,需要使用setFilter过滤,类似SQL的WHERE group_id=2 $cl->setFilter('group_id',array(2)); //sql_attr_uint等类型的属性字段,也可以设置过滤范围,类似SQL的WHERE group_id2>=6 AND group_id2<=8 $cl->SetFilterRange('group_id2',6,8); */ //取从头开始的前20条数据,0,20类似SQl语句的LIMIT 0,20 $cl->SetLimits(0,20); //在做索引时,没有进行 sql_attr_类型 设置的字段,可以作为“搜索字符串”,进行全文搜索 $res = $cl->Query ( '搜索字符串', "*" ); //"*"表示在所有索引里面同时搜索,"索引名称(例如test或者test,test2)"则表示搜索指定的 //如果需要搜索指定全文字段的内容,可以使用扩展匹配模式: //$cl->SetMatchMode(SPH_MATCH_EXTENDED); //$res=cl->Query( '@title (测试)' , "*"); //$res=cl->Query( '@title (测试) @content ('网络')' , "*"); echo '<pre>'; print_r($res['matches']); print_r($res); print_r($cl->GetLastError()); print_r($cl->GetLastWarning()); echo '</pre>'; |
给字典加入新词
/usr/local/mmseg3/etc下有个unigram.txt文件
这个是字典的文本版本
加入新词需要加入两行,如
新浪微博 1
x:1
然后执行命令mmseg -u unigram.txt
将生成一个unigram.txt.lib文件,将etc目录里的uni.lib改名,并把这个文件改名为uni.lib,重新生成索引
详细一点的可以看这里
http://hi.baidu.com/cubeking/blog/item/9aedb7a67b5b95e29152ee5c.html
这是一个比较重要的章节. Core Data是一个数据框架,主要目的是自动化管理数据,脱离实际的数据引擎接口,用统一的方式操作数据,比较类似于java中的hibernate?
* 要使用core data,需要#import
NSManagedObjectModel 用来描述应用中的数据模型(entities).
创建一个NSManagedObjectModel
1 2 | // 将合并所有在给出bundles参数内的model,如果mergedModelFromBundles传入nil则自动读取main bundle的 NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; |
NSPersistentStoreCoordinator 是永久存储介质(关系数据库)和managed object context中间的联系层,context必须有coordinator设置,否则就是不能工作的context。
1 2 3 4 | // 初始化 NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel]; // 设置数据库类型,数据库url等 [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error] |
NSManagedObjectContext 用于管理managed object
1 2 | self.context = [[[NSManagedObjectContext alloc] init] autorelease]; [self.context setPersistentStoreCoordinator:persistentStoreCoordinator]; |
以上过程合并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | NSError *error; NSURL *url = [NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingString:@"/Documents/cdintro_00.sqlite"]]; // Init the model, coordinator, context NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel]; if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error]) NSLog(@"Error: %@", [error localizedDescription]); else { self.context = [[[NSManagedObjectContext alloc] init] autorelease]; [self.context setPersistentStoreCoordinator:persistentStoreCoordinator]; } [persistentStoreCoordinator release]; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // Insert objects for department and two people, setting their properties Department *department = (Department *)[NSEntityDescription insertNewObjectForEntityForName:@"Department" inManagedObjectContext:self.context]; department.groupName = @"Office of Personnel Management"; Person *person1 = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.context]; person1.name = @"John Smith"; person1.birthday = [self dateFromString:@"12-1-1901"]; person1.department = department; Person *person2 = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.context]; person2.name = @"Jane Doe"; person2.birthday = [self dateFromString:@"4-13-1922"]; person2.department = department; department.manager = person1; department.members = [NSSet setWithObjects:person1, person2, nil]; // Save the data NSError *error; if (![self.context save:&error]) NSLog(@"Error: %@", [error localizedDescription]); |
NSEntityDescription 用来描述core data中的一个entity(对于数据库来说是一个表,对于代码来说是一个类)
NSManagedObject创建的另外一个方法
– initWithEntity:insertIntoManagedObjectContext:
会触发awakeFromInsert ,类似的方法同样还有awakeFromFetch
1 2 3 4 5 |
NSFetchRequest用于描述一个查询中的参数(条件,排序,结果数等等)。
NSSortDescriptor 用于描述查询的排序方式,并可以提供自定义的排序比较方法。
NSFetchedResultsController用于管理查询返回结果并提供给UITableView。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | - (void) fetchObjects { // 创建Request NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:[NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.context]]; // 添加一个排序描述 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:nil]; NSArray *descriptors = [NSArray arrayWithObject:sortDescriptor]; [fetchRequest setSortDescriptors:descriptors]; [sortDescriptor release]; // 初始化results controller,cache叫Root NSError *error; self.results = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:nil cacheName:@"Root"]; self.results.delegate = self; // 查询 if (![[self results] performFetch:&error]) NSLog(@"Error: %@", [error localizedDescription]); [self.results release]; [fetchRequest release]; } |
创建fetch request 模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | NSManagedObjectModel *model = <#Get a model#>; NSFetchRequest *requestTemplate = [[NSFetchRequest alloc] init]; NSEntityDescription *publicationEntity = [[model entitiesByName] objectForKey:@"Publication"]; [requestTemplate setEntity:publicationEntity]; NSPredicate *predicateTemplate = [NSPredicate predicateWithFormat: @"(mainAuthor.firstName like[cd] $FIRST_NAME) AND \ (mainAuthor.lastName like[cd] $LAST_NAME) AND \ (publicationDate > $DATE)"]; [requestTemplate setPredicate:predicateTemplate]; [model setFetchRequestTemplate:requestTemplate forName:@"PublicationsForAuthorSinceDate"]; [requestTemplate release]; |
获取模板并查询
1 2 3 4 5 6 7 8 9 10 | NSManagedObjectModel *model = <#Get a model#>; NSError *error = nil; NSDictionary *substitutionDictionary = [NSDictionary dictionaryWithObjectsAndKeys: @"Fiona", @"FIRST_NAME", @"Verde", @"LAST_NAME", [NSDate dateWithTimeIntervalSinceNow:-31356000], @"DATE", nil]; NSFetchRequest *fetchRequest = [model fetchRequestFromTemplateWithName:@"PublicationsForAuthorSinceDate" substitutionVariables:substitutionDictionary]; NSArray *results = [aManagedObjectContext executeFetchRequest:fetchRequest error:&error]; |
* 如果模板中没有可替换的参数,你必须用以下两种方法之一
Use fetchRequestFromTemplateWithName:substitutionVariables: and pass nil as the variables argument; or
Use fetchRequestTemplateForName: and copy the result.
If you try to use the fetch request returned by fetchRequestTemplateForName:, this generates an exception (“Can’t modify a named fetch request in an immutable model”).
NSFetchedResultsControllerDelegate 协议,当results controller的结果集增加,修改,删除记录时会触发这些代理方法
– controllerWillChangeContent:
– controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
– controller:didChangeSection:atIndex:forChangeType:
– controllerDidChangeContent:
NSFetchedResultsController和UITableView的结合
fetch时设置sectionNameKeyPath,用于在table view中显示index title
1 | self.results = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:@"section" cacheName:@"Root"]; |
以下是table view相关的delegate方法,其中
tableView:titleForHeaderInSection:
sectionIndexTitlesForTableView:
和设置index title有关
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // Retrieve or create a cell UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"basic cell"]; if (!cell) cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"basic cell"] autorelease]; // Recover object from fetched results NSManagedObject *managedObject = [self.results objectAtIndexPath:indexPath]; cell.textLabel.text = [managedObject valueForKey:@"name"]; UIColor *color = [self getColor:[managedObject valueForKey:@"color"]]; cell.textLabel.textColor = ([[managedObject valueForKey:@"color"] hasPrefix:@"FFFFFF"]) ? [UIColor blackColor] : color; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // When a row is selected, color the navigation bar accordingly NSManagedObject *managedObject = [self.results objectAtIndexPath:indexPath]; UIColor *color = [self getColor:[managedObject valueForKey:@"color"]]; self.navigationController.navigationBar.tintColor = color; } #pragma mark Sections - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Use the fetched results section count return [[self.results sections] count]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the count for each section return [[[self.results sections] objectAtIndex:section] numberOfObjects]; } - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)aTableView { // Return the array of section index titles return self.results.sectionIndexTitles; } - (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section { // Return the title for a given section NSArray *titles = [self.results sectionIndexTitles]; if (titles.count <= section) return @"Error"; return [titles objectAtIndex:section]; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { // Query the titles for the section associated with an index title return [self.results.sectionIndexTitles indexOfObject:title]; } |
条件查询
1 |
table view edit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // delete request if (editingStyle == UITableViewCellEditingStyleDelete) { NSError *error = nil; [self.context deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]]; if (![self.context save:&error]) NSLog(@"Error: %@", [error localizedDescription]); } // update buttons after delete action [self setBarButtonItems]; // update sections [self performFetch]; } |
每个context有各自的undoManager
self.undoManager = self.context.undoManager;
添加记录
1 2 3 4 5 6 7 8 9 10 11 12 13 | [self.context.undoManager beginUndoGrouping]; // build a new item and set its action field ToDoItem *item = (ToDoItem *)[NSEntityDescription insertNewObjectForEntityForName:@"ToDoItem" inManagedObjectContext:self.context]; item.action = todoAction; item.sectionName = [[todoAction substringToIndex:1] uppercaseString]; // save the new item NSError *error; if (![self.context save:&error]) NSLog(@"Error: %@", [error localizedDescription]); [self.context.undoManager endUndoGrouping]; [self.context.undoManager setActionName:@"Add"]; |
删除记录
1 2 3 4 5 6 7 8 9 10 11 12 | [self.context.undoManager beginUndoGrouping]; // delete request if (editingStyle == UITableViewCellEditingStyleDelete) { NSError *error = nil; [self.context deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]]; if (![self.context save:&error]) NSLog(@"Error: %@", [error localizedDescription]); } [self.context.undoManager endUndoGrouping]; [self.context.undoManager setActionName:@"Delete"]; |
注:ios undo/redo的指令默认是靠晃动设备完成的。ios模拟器上shake的快捷键是control+command+z
如果要禁止晃动产生undo
1 | application.applicationSupportsShakeToEdit = NO; |
更多undo信息,请阅读Using Undo on iPhone
相关源码:
C19-CoreData(来自The.iPhone.Developers.Cookbook,2nd)
CoreDataBooks