Archive for the '数据库' Category

转:十五分钟介绍 Redis 数据结构

星期二, 十一月 1st, 2011

http://www.oschina.net/question/54100_28977

Sphinx 安装备忘

星期五, 十月 28th, 2011

以前装过一次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
require_once ( "sphinxapi.php" );

$cl = new SphinxClient ();
$cl->SetServer ( '127.0.0.1', 9312);
$cl->SetConnectTimeout ( 3 );
$cl->SetArrayResult ( true );
$cl->SetMatchMode ( SPH_MATCH_ANY);
$res = $cl->Query ( '网络搜索', "*" );

print_r($cl);
print_r($res);

另外还有一些高级用法

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

Cocoa notes (18) Core Data

星期四, 五月 26th, 2011

这是一个比较重要的章节. Core Data是一个数据框架,主要目的是自动化管理数据,脱离实际的数据引擎接口,用统一的方式操作数据,比较类似于java中的hibernate?

* 要使用core data,需要#import

准备环境(初始化model, coordinator, context)

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
- (void) awakeFromInsert
{
    [super awakeFromInsert];
    [self setCreationDate:[NSDate date]];
}

查询数据

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
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query];

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];
}

让Core Data支持undo,redo

每个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