月度归档:2013年12月

js的网络序转换

js没有原生的网络序和主机序的转换接口。但是随着nodejs的火,也开始有这个包了: https://npmjs.org/package/network-byte-order‎

稍微封装下就能放到js中使用了。

sphinx的检索字段配置限制

问题现象
前天很有自信的上传了sphinx配置,结果重建索引出现”No fields in schema”的错误。第一反应是自己姿势不对,仔细检查了相关配置,没发现任何问题。纠结了半天,注释掉新加的sql_attr_string C,然后重建索引成功了,初感不解,然后生效C,注释掉sql_attr_string B,重建也成功了,越觉莫名其妙。

解决办法】
各方途径调查原因如下:sphinx对于sql数据源需要至少一个sql_field_string,当没有指定sql_field_string时会将数据源中没有明确指定为sql_attr_string的字符串字段用来做sql_field_string。因为数据源中总共只有ABC三个字符串数据,这就是为什么全部字符串字段设为sql_attr_string时不能重建索引,而随便注释一条sql_attr_string,重建索引都能成功的原因。

sphinx返回匹配的字段

1. 问题产生的背景
sphinx有一个评分模式
SPH_RANK_FIELDMASK可以在结果中带回所匹配的字段的32位掩码。例如有5个字段ABCDE是sql_field_string,比如一条记录只命中A字段,那么@weight的值就是1,如果5个字段都命中,那么@weight的值就是32。但是我们通常都习惯用SPH_RANK_PROXIMITY_BM25或者SPH_RANK_SPH04等这种能够代表真实相关度的评分模式,既想用其他评分器又想明确知道当前匹配到哪几个字段的矛盾就不可避免了。

2. 目前的解决办法
去官方论坛,stackflow等地方查阅了相关讨论,目前貌似都木有完美解决方法。虽然各种相关讨论都希望这个值作为内部的一个属性直接返回,但至少目前看来,官方开发特性没有这方面的打算。现在普遍的做法是多做一次查询,第一次用自己的评分模式,第二次用SPH_RANK_FIELDMASK这种模式,然后在第一次查询中取数据,在第二次查询中取对应文档的匹配的字段掩码来综合业务逻辑。

3. 我是这么整的
虽然sphinx的多查询有很多优化,通常也不会造成性能上多大的损失,但是毕竟这种方法还是比较费事儿的。考虑到sphinx评分器支持自定义,那我们就可以在某些条件下携带这些数据。例如,假设我的需要参与检索的字段数为n个,那么field_mask的值就不会大于2^n,因此我们只需要把其他评分器的值向左移n位就能保证不会丢失数据。(以SPH_RANK_SPH04+SPH_RANK_FIELDMASK两者融合为例)

当然需要注意的是,这个值不能超过32位整型上限,需要精确的保证需要的公式值所占的位数 + 进行检索的字段数 < 32 即可(所以像这里user_weight的值选取就需要仔细斟酌)。另外这样做了之后@weight的值就是这两者的融合了,因此如果想用之前的评分的话,只需重新定义一个@weight / 2^n as f_new_weight字段,按上面例子的话就可以等价于SPH_RANK_SPH04了。

参考文献
http://sphinxsearch.com/blog/2010/08/17/how-sphinx-relevance-ranking-works/ http://sphinxsearch.com/docs/archives/manual-2.0.8.html#weighting

github api之美

现在互联网上的api真是如雨后春笋一般,几乎所有平台方都或多或少提供web api了,因为web已经把异构的系统,多样的媒介无差异的连接在了一起。github的api应该是目前用着最舒心的api了,因为其自描述的接口完全无需解释,灵活的请求方法和参数毫无门槛。
1. github的api是神马样子,看看以下三个链接的结果就完全明白了
a) https://api.github.com/
b) https://api.github.com/user和https://api.github.com/users/{github-name}
c) http://developer.github.com/v3
2. 带来的启发
1). api列表(api.xxx.com)
很多时候查阅本平台提供的api是件比较麻烦的事,直接在api的空接口上以开发友好的方式返回所有api的概况则会显得非常直观。所以api的平台方应该有个顶层接口来返回api列表。
2). 具体api(api.xxx.com/[api-name])
接口是层次递进的,api.github.com展示所有api, https://api.github.com/[api-name]则对应具体接口,当调用出错时给予提示和文档url。网上很多接口调用出错时,不会以友好方式返回错误信息和api文档地址,这个是比较粗心的。
3). api文档中心(developer.xxx.com/[version number])
平台所有文档,且能适配api版本。版本概念在所有api中都非常重要,某些api会直接提供版本参数,但大部分api都只处理最新版本,对老版本调用方式统一返回提示信息。在文档url这个地方加上版本号,方便知道目前接口的版本。还有文档的组织实际上是给开发者看的,那么形式就必须简单试用,github这种文档格式就非常好:接口介绍 -> 请求方法 -> 参数说明 -> example(request + response)
4). api请求/响应格式适配
get参数使用标准格式,post方法使用Json。这些细微改变使用工具构建请求更加容易。同时api_url/{sp1}/{sp2}?s3=yyy等价于api_url?s1=sp1&s2=sp2&s3=yyy这种形式的适配让接口更加灵活。由于目前互联网传输中最流行的数据格式是json,response统一都用json做处理。当然也马目前很多平台api带返回格式参数的,通常提供xml和json返回。
5). api粒度
api接口的划分是个技术活,不能太细也不能太粗。逻辑上就有差别的就拆分成两条接口,逻辑上无差别,针对个人属性的,可以用类似与api_usrl/{user_name}?xxxxx的方式来扩展api进行适配。

sphinx新特性展望

sphinx开发团队的速度着实让人害怕,最近基本都是都是2个月左右就一个正式版。目前2.0.8应该算是用得最多的一个版本,原因我想有两点:
1). 2.0.8到2.0.9间隔较长,差不多4个月,使用sphinx的估计已经妥妥的用在了自己生成环境上,再作变动成本会较高
2). 2.0.8之后的release版本新特性还没有达到不能拒绝的程度。
  昨天在群里面有人聊到了2.2.1 beta版的新特性,然后偶就再一次到官网去琢磨了下。以前的版本特性更多的体现在对实时索引的优化和对json支持的优化,2.2.1真的有几项feature让人不能拒绝。

1.  Integration with RLP for Chinese segmentation.
内建中文分词。在这之前我们只有两种选择:
1). 先用分词工具分好词再去创建索引;
2).使用国内coreseek或者sfc之类的修改版在索引时分词
第一种方法处理起来就麻烦一些,属于sphinx干不了时的变通方法,相当于把一段文本分成有固定分隔符的文本,然后索引时配置以这个分隔符来区分汉字建立索引。
第二种方法用起来木有问题,但是完全跟不上官方的节奏,神马新特性更是无从谈起。
这个特性绝对无法拒绝。

2. New data source for indexing CSV/TSV files in the same fashion as for XML files.
支持csv/tsv这些文件了。好处是神马?就是你现在可以用很简单的明文了。在这之前我们能做的不多:基本只有coreseek能用万能的python来聚合各种数据源,sphinx官方就只有xml和db,xml虽然是明文,但按这种结构组织还不是那么方便。现在你可以用linux下各种shell命令工具来聚合数据,这里又让人有了很大的想象空间。

3. GEODIST() now uses (by default) a lighter algorithm which is based on Polar Flat-Earth formula.  It’s now possible to specify the input/output unit type as well as the calculation algorithm to be used.
以前geodist这个函数是很慢的,因为他使劲的算准确,相比 Polar Flat-Earth formula这个要慢很多。之前要用到geo的计算,基本上都是把Polar Flat-Earth formula算式写到sql语句中。还有就是老的单位是弧度,所以以前算了geo真是要写很多”废话”,现在支持各种单位,一下爽多了。

相关姊妹篇: 关于sphinx – 我有话要说

opensuse 13.1支持ralink的一系列无线网卡芯片了

万恶的普联 tp-link TL-WDN3321 300M双频无线USB网卡 (TL-WDN3321 1.0)终于被linux内核原生支持了,终于不用摆脱官方驱动的各种不稳定掉线的节奏了。这款usb无线网卡采用的是ralink公司的RT5572芯片,得益于新内核的无线网卡驱动,opensuse 13.1 总算是成功支撑了。

opensuse 13.1下网络已经能够识别出来该设备了。lsusb 可以看到识别出ralink了,同时lsmod也可以看到类似rt2x00usb等等的模块了。