一、OSQA搭建

直接按照wiki:http://wiki.osqa.net/display/docs/Home

根据自己的系统来选择安装。我用的ubuntu+python2.6+django1.3 (1.4能用,但是需要改很多地方)。安装过程可以参考wiki,解释得已经很详细。过程中出现nomodule之类的都easy_install就可以了。

Osqa下载之后要配几个地方
 settings_local.py.dist重命名成settings_local.py。settings_local.py需要修改的地方:

        DATABASES={
        'default':{
        'ENGINE':'django.db.backends.mysql',
        'NAME':'osqa',
        'USER':'root',
        'PASSWORD':'root',
        'HOST':'127.0.0.1',
        'PORT':'3306',
        }

 根据自己的设置填写

    APP_URL='http://127.0.0.1:8000'
    LANGUAGE_CODE='cn'#汉化得已经很不错了
    DJANGO_VERSION=1.3#填写自己的django版本
    DISABLED_MODULES=['mysqlfulltext','books','recaptcha','project_badges']#trunk的默认用的是mysql全文索引,需要把这个加到diabledmodule!

如果用sphinx做全文搜索的话,追加

        SPHINX_API_VERSION=0x116#refertodjangosphinxdocumentation
        SPHINX_SEARCH_INDICES=('search_question_index',)#atupleofindexnamesrememberabouta#commaafterthe
        SPHINX_SERVER='localhost'
        SPHINX_PORT=9312

并且在settings.py

        INSTALLED_APPS=[
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sites',
        'django.contrib.admin',
        'django.contrib.humanize',
        'django.contrib.sitemaps',
        'django.contrib.markup',
        'forum',
        'djangosphinx',
        ]

当然,要用sphinx就easy_install django-sphinx和sphinxsearch。

到此,基本配置都已完成,不管用apache还是简单的manage.pyrunserver的方式都可以启动,看到界面了。配置邮件可以参考:(注:原文未说明)

接下来,注意到添加感兴趣标签的时候,输入标签名点击添加就可以看到刚才的标签已经在上面了,可是刷新之后发现不见了。于是查看代码之后发现这句:

    froumviewscommands.py line 536
    try:
    t = Tag.objects.get(name=tag)
    mt = MarkedTag(user=request.user, reason=reason, tag=t)
    mt.save()
    except :
    pass

    就是说,如果该标签不存在在数据库,不是已有的标签,就会静静地pass,而前端还能显示能加到。
    osqa1.png
    官网也是这个样子……….这样的方式不太友好,在没有该标签的时候应该给用户一个友好提示…


二、Coreseek实现OSQA的搜索
1. 两个问题

1、Mysql全文索引不堪重用
2、搜索问题显示没有match的。即使输入的是某个标题的关键字也搜不到,最后几天便一直卡在这个问题上。

Google了N多,试了又试,无意间在settings.py所在的目录看到有个log文件夹。里面有个django.osqa.log文件Tail-fdjango.osqa.log,在页面发一个搜索请求,看到了它其实用的是mysql的全文索引。如果表里没有数据,则搜索不到问题。
后来终于在/home/osqa/osqaweb/log目录下的django.osqa.log文件中看到这句,这个表forum_mysqlftsindex就是用mysql做全文索引建的表,建个trigger在每次人问问题和回答问题,都会触发这个触发器,并且重新将该问题相关的全部内容都重新更新到索引表:
osqa2.png

接下来试试搜索问题 也能看到这样:
osqa3.png

所以,很明显,默认的用的是mysqlfulltext,搜索的时候也走的这条线。

在这之前,试图很多次开启sphinxfulltext模块的时候,settings等地方需要都改了,需要配的都配了,但是始终在sphinx的服务端没有看到任何请求过来,coreseek虽然是第一次使用,但是对sphinx已经用了很久,所以能肯定sphinx的server端肯定是没有问题的。在看到上面的log之后就确定是默认走的是mysql的全文索引,于是在disabledmodule里将mysqlfulltext加上。就试了试搜索,就看到如下的结果:
osqa4.png

应该走的是django的模糊匹配,我的keyword是 ask,它就到forum_node这个问题表中用like ‘%ask%’这样的模糊匹配去取数据。当然,直接去这里找当然能找到了,页面也能显示相应的问题了,但是like毕竟不是长久之计,本身也对MySQL数据库产生巨大的压力,也就是说,表forum_mysqlftsindex就是用mysql做全文索引建的表,那么现在咱们得废掉这个MySQL本身提供的全文索引,寻找一种更为有效的全文索引方式或解决方案。


2. 基于sphinx之上的Coreseek实现搜索
下面就考虑给osqa的搜索用sphinx实现。因为包含中文搜索,虽然sphinx可以通过设定编码和有效字符集支持中文,但是中文分词搞不定,就用coreseek来实现,coreseek整合了分词+搜索。

(1)第一步安装coreseek:http://www.coreseek.cn/
 coreseek官网稳定版是3.2.14,是基于sphinx0.9.9的。
安装过程也没什么,直接参照:

http://www.coreseek.cn/products/products-install/install_on_bsd_linux/

先安装分词模块mmseg,出现如下所示的结果就可以了:

$ /usr/local/mmseg3/bin/mmseg -d /usr/local/mmseg3/etc src/t1.txt

中文/x 分/x 词/x 测试/x
中国人/x 上海市/x

Word Splite took: 1 ms

(2 )第二步是csft

看到如下所示表示已经安装成功:

$ /usr/local/coreseek/bin/indexer -c /usr/local/coreseek/etc/sphinx-min.conf.dist

##以下为正常测试时的提示信息:
Coreseek Fulltext 3.2 [ Sphinx 0.9.9-release (r2117)]
Copyright (c) 2007-2010,
Beijing Choice Software Technologies Inc (http://www.coreseek.com)
using config file '/usr/local/coreseek/etc/sphinx-min.conf.dist'...
total 0 reads, 0.000 sec, 0.0 kb/call avg, 0.0 msec/call avg
total 0 writes, 0.000 sec, 0.0 kb/call avg, 0.0 msec/call avg

(3) OSQA内Sphinx配置文件
接下来为我们的问题搜索写sphinx配置文件,我的配置文件如下:

    #源定义
    sourcebase_source
    {
    type=mysql
    sql_host=localhost
    sql_user=root
    sql_pass=root
    sql_db=osqa
    sql_port=3306
    sql_query_pre=SETNAMESutf8
    sql_query_pre=SETSESSIONquery_cache_type=OFF
    sql_query_info_pre=SETNAMESutf8
    sql_range_step=1000
    sql_query=
    }
    #index定义
    indexbase_index
    {
    path=
    source=base_source#对应的source名称
    docinfo=extern
    mlock=0
    morphology=none
    min_word_len=1
    html_strip=0
    #中文分词配置,详情请查看:http://www.coreseek.cn/products-install/coreseek_mmseg/
    charset_dictpath=/usr/local/mmseg3/etc/#BSD、Linux环境下设置,/符号结尾
    #charset_dictpath=etc/#Windows环境下设置,/符号结尾,最好给出绝对路径,例如:C:/usr/local/coreseek/etc/...
    charset_type=zh_cn.utf-8
    ngram_len=0
    }
    sourcesearch_question_source:base_source
    {
    sql_query_range=selectmin(id),max(id)fromforum_node
    sql_query=SELECTquestion.id,question.title,author.username,question.tagnames,question.body,
    GROUP_CONCAT(answer.body)asanswer_bodiesFROMforum_nodeASquestion,forum_nodeASanswer,
    auth_userASauthorWHEREanswer.parent_id=question.idANDquestion.author_id=author.id
    Andquestion.id>=$startandquestion.idDATE_FORMAT(NOW(),'%Y-%m-%d')
    }
    indexsearch_question_index:base_index
    {
    source=search_question_source
    path=/ROOT/sphinx/index/search_question
    }
    indexdelta_search_question_index:search_question_index
    {
    source=delta_search_question_source
    path=/ROOT/sphinx/index/delta_search_question
    }
    #全局index定义
    indexer
    {
    mem_limit=128M
    }
    #searchd服务定义
    searchd
    {
    listen=9312
    read_timeout=5
    max_children=30
    max_matches=1000
    seamless_rotate=0
    preopen_indexes=0
    unlink_old=1
    pid_file=/ROOT/sphinx/log/searchd_osqa.pid#请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
    log=/ROOT/sphinx/log/searchd_osqa.log#请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
    query_log=/ROOT/sphinx/log/query_osqa.log#请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...

可以放在任何文件夹下只要建索引的时候指定就好。比如我的是放在/ROOT/sphinx/conf/sphinx_osqa.conf,接下来建索引:

indexer -c /ROOT/sphinx/conf/sphinx_osqa.conf --all –rotate

Base_index的警告可以忽略,然后启动守护进程:

searchd –c /ROOT/sphinx/conf/sphinx_osqa.conf

到此,sphinx的服务端都已经弄好,守护进程searchd在9312端口等待客户端发query。可以简单测试一下

search –c /ROOT/sphinx/conf/sphinx_osqa.confkeywords

3. Sphinx服务端配置的几个问题
Sphinx服务端配置已经完成,虽然自从diable掉mysqlfulltext之后就可以搜到问题,但是用的是Like%keyword%形式的请求。我们现在需要改的有三处:
(1)在/forum/models/question.py
    在Question类加入

        search=SphinxSearch(
        index='search_question_index',
        mode='SPH_MATCH_ALL',
        )

 自己根据需求配置,比如设置权重之类的。
 (2)加入sphinx search,引用

from djangosphinx.models import SphinxSearch

(3) QuestionManager类加入

queryset=Question.search.query(keywords)
将命中的id取出来存成list结构,比如,存到变量ids里,然后直接返回

return False,self.filter(id__in=ids)

这样就返回了命中的id的所有问题。当然这种in的方式如果ids的数据量小的时候还可以,大了之后也不行,所以,后续应该考虑分页的方式来呈现更多的结果。
当然,最终能在服务器端上看到已经有收到请求了,如下图所示:
osqa5.png
至此,之前搜到不到关键词/tag的问题成功解决。也就是说,咱们的StackOverflow的原型OSQA已经搭建完成,接下来,便是一系列修改完善优化的工作。

感谢技术知己之一罗勍:http://weibo.com/u/1909128871。(项目已终止,2012.07.17)。