推荐阅读《Event-based programming: taking events to the limit》

July 1st, 2009 :: jackyz

Event Based Programming

软件开发的奥义就是:分而治之。

代码世界从来都是一个充斥着耦合的世界,在这个世界里有着各种各样的耦合:静态耦合,动态耦合,类型耦合,逻辑耦合,空间耦合,时间耦合……。可以说,通常而言,一个良好的软件开发,最重要的一个步骤就是使用各种各样的工具来解耦目标系统,使其变成更小,更简单,更易于理解,更便于测试,更……的逻辑单元。完成这一阶段之后,剩下来的,差不多就都是体力活了。

然而,需要强调的一点是,我们要追求的绝对不是一个没有耦合的系统(我很怀疑,可能存在这样的系统么?)。实际上,一些耦合正是业务逻辑的表达,无法去除。我的意思是,或许我们致力于去除的,只是一部分“实现层面的耦合”。话说到这个分上,已经有点 “as simple as possible but not simpler” 的味道,赶紧打住了。

为了解耦系统,我们发展出了种种工具:接口、代理、设计模式……。在所有这些解耦工具之中,最为强悍的恐怕就是消息系统,它的解耦效果,不仅仅体现在概念维度上(接口的使用者和实现者),而且也体现在空间维度上(分布式消息)时间维度上(异步消息)。关于这一点,我这里推荐的这本书,讲得比较清楚。

我们很幸运 Apress 在 2006 年推出的《Event-based programming: taking events to the limit》现在已经可以在 Google Book 上全文读到。而相应的豆瓣页面也正等着大家去丰富。

这里需要强调的一点是:解耦从来都是有代价的,更为彻底的解耦通常就意味着更难把握。对于广大 Erlangor 来说,这本书中的代码和实例,可能不是那么有参考价值,但我们使用的语言正是完全建立在“基于消息编程的架构”之上的,多读一点参考资料,至少是第一章,当然也是很有必要的。

感谢 Jeffry Zhao 在 Twitter 上的投递。

misc ,

QCon Joe Armstong Show

June 11th, 2009 :: jackyz

InfoQ 英文站放出了6月8日在 QCon 上 Joe Armstrong 老头的演讲视频 —— 《Functions + Messages + Concurrency = Erlang》各位粉丝,请点[这里]组团前往围观。

misc

Erlang 引用检查小脚本

June 11th, 2009 :: jackyz

Erlang 的编译检查相当宽松,有时候,会让人觉得宽松得过了头。比如说,在一个模块中调用另外一个模块的函数,如果被调用的函数还没有定义(比如说,忘了写或者拼写有误),编译器是不会给出任何警告的。如果你看编译没有错误就冒冒失失地运行的话,得到一堆莫名其妙的错误。这通常会搞的人很挫折,而检查这种问题也要浪费不少时间。下面这个脚本是解决这种烦恼的最简陋形式。

#!/bin/bash
erl -pz ebin deps/*/ebin -noshell \
  -eval "io:format(\"~p~n\", [xref:d(\"ebin\")]), c:q()."

需要说明的是,未对输出进行任何处理,能看,好懂,但是相当之简陋,有兴趣的同学,可以自己动手美化之。

misc

[转]Erlang的类型系统和静态分析

June 9th, 2009 :: jackyz

转载说明

“Erlang 是动态类型的语言,因而不能进行静态分析,所生成的文档也不包含有助于理解的类型信息”——这是惯常的看法,广为流行,而且被看作是 Erlang 在开发大型系统时的一个短板(大型系统意味着更强烈的静态分析需求和更严重的依赖文档进行沟通)。

然而 Erlang 是一个有着 20 多年历史的成熟系统,它早已发展出了一套自己的类型标注系统,不仅用来生成文档,更重要的是可以据此对源码进行静态分析,通过程序来排除一些低级的和隐藏的错误。在这方面, Erlang OTP 的源码本身及其文档就是最好的例子。在 《Erlang 程序设计》 的附录A部分,对于这个系统的使用已经进行了充分的说明。

需要强调的一点是在 Erlang 语言的背后还有一个活跃的社区(后者更为重要),其 EPP 过程一直都在持续不断地推进语言本身的进化。这方面最新的成果便是:在 R13 中,将此前文档级的 @spec,@type 标注升级为语言级的 -spec,-type 标注。可以预期的一点是,在未来的版本中,这些方面仍将持续推进。

litaocheng 同学的这篇“Erlang类型及函数声明规格”,风格严谨,论述详尽,涵盖了最新的语言特性,是任何一个程序员想要开发“严肃 Erlang 程序”的必读文档。

Read more…

study , , ,

google wave 冲击波

June 2nd, 2009 :: jackyz

警告:本文纯属六一吹水,看客童鞋小心忽悠。

认识我有一段时间的朋友,肯定都在不同的场合分别听到过我对 “实时 Web 应用” 的鼓吹。有兴趣可以翻看去年 “CN Erlounge III” 上的《Realtime Web Application》,今年“Ajax 群英会”上的《实时 Web 应用》以及“BeijingOpenParty ——晚春夜曲”上的《实时 Web 应用中间件》。

虽说俺对于实时 Web 应用的爆发早有心理准备,但在5月31日,第一眼看到 Google Wave 的时候,还是和大家一样,被震到了。一是没有想到,实时 Web 应用还可以这么玩,太 TM 有创意了;二是没有想到,在这个“还没看清怎么玩”的领域 Google 竟然这么快就现身了,太 TM 神速了。(我很好奇,是怎样的公司文化和人才机制才能孕育这么恐怖的创新能力呢?)。

好吧,惊叹就到这里了(拍 Google 的马屁,那是众 G 粉的乐子,哪轮得着我呀)。下面照例,进入咱们的 “超强脱水” 上干货环节。

创新——Google Wave 创造性的解决了“实时”与“非实时”之间的无缝连接

非实时就是 Email ,实时就是 IM ,这两者的用户体验是如此的迥异,以至于此前试图将这两者统一起来的努力均告失败。而 Google Wave 所采用的方式则是老调重弹却又谱出新章的 Version Control —— 一个 Wave 就象是 Wiki 上的一篇文章,是一个有着版本控制的信息实体,被多个 participants (也就是用户)所共享。在这个隐喻下,非实时的访问就变成了“获取当前版本”,而实时的访问则符合“跟踪当前版本的所有更新”(所有的更新都通过实时消息广播给所有的 participants)。至此,让人目瞪口呆的 Replay 功能,也变得极其简单,只不过是版本控制的酷眩呈现而已。

现在看到很多说法,从“将会一统天下”到“未来互联网的基础应用”,等等,溢美之词不一而足。姑且认为这些都是 G 粉丝美好的 YY 吧。无须过渡诠释,咱们抛开 Google 的明星气质和强大的号召力不谈(借助这些, Google Wave 真的有成为 THE ONE 潜质也说不定)。单从“请下神坛”的“低俗化”角度, Google Wave 最本质的创新其实就是 Realtime + Wiki 并在此基础上进行各种扩充而已。有心山寨的各位山大王,从这里开始抄就对了。

技术——基于 Web 的 Realtime 技术,以及有 Google 特色的开发框架

在创新面前,任何实现层面的技术都会显得黯然失色。虽然目前还无缘得见 Google Wave 的 Realtime 实现技术,但大致可以猜出肯定是 Web Socket 或者 Ajax Long Poll 中的一种(很有可能是前者)。从技术层面而言,早已经算不上是新鲜事物了。然而有 Google 特色的开发框架(这个句式怎么听来这么耳熟呢),仍让人感到新奇。展现层的扩展直接使用了 Gadgets 模式。逻辑层的扩展则直接使用了 App Engine 的 Web 模型。

应该说,这一整套扩展方案充满了 “Google 的味道”,而且,这个模型肯定是能用的。除了 Google 系扩展一贯的稍嫌“重型”之外,唯一让人感到担心的,恐怕是这种逻辑扩展模型的抗压性。虽说使用了批量发送作为两个层次之间的阻抗匹配,但这种方法实际上仍然是将实时性更高的 Realtime 通讯构建在了实时性较低的 HTTP 通讯之上,不知道这会不会带来潜在的问题。

战略——Browser Platform/OpenSocial/OpenStand阳谋的最新尝试

Google 对 M$ 的阳谋就是 Browser Platform 战略,浏览器即平台——管你什么设备,也不关心什么 OS ,只要有一个符合 HTML5 标准的浏览器,走到哪里都是一样的用。无论是 gOS 也好,Chrome 也罢,还有 Google 对 Firefox 的大力支持,所有东西全都围绕这个核心展开。利益攸关嘛,所以,在 HTML5 上 Google 的心急和 Microsoft 的拖沓,也就显得很好理解。而这次的 Google Wave 也没有例外。以超眩的用户体验为“ HTML5 兼容浏览器”阵营奉上自己的 Killer App。民心向背是革命成败的关键,Google 的革命理论学得不错。

M$ 之外,另外一些会让 Google 这样的巨头感到巨头疼的恐怕也就只有 Facebook/Twitter 这一票跟在屁股后面猛追不舍的 SNS 了。OpenSocial 战略就是分化瓦解 SNS 集团的阳谋,但似乎不大奏效。第二梯队的 SNS 始终各怀鬼胎,最起码的 Open Platform 尚且无法贯彻,更进一步的 OpenSocial 缺乏动力也就见怪不怪了(从国内 SNS 对“开放平台”的暧昧态度就可窥见一斑)。因为无法摆平各方利益,技术相当领先的 OpenSocial 几乎快到了要沦为鸡肋的境地。而第一梯队的 Facebook 之辈用户基数则继续保持爆炸性增长,搞得 Google 很是窝心的说。如果说之前的 OpenSocial 是“跟在后面搞破坏”,那么此番祭出的 Wave 则是“抢在前面打埋伏”,而且还摆明了车马,将要彻底开源,欢迎大家山寨。用心可谓良苦,但效果目前还说不好。用户到底是会被 Network 粘得死死的,还是会被 Wave 勾得心痒痒进而纷至沓来,仍然还需要时间的检验。但,计以至此却已然到了尽头,再没有回转的余地;如若不售,后续的手段恐怕只剩下收购一条了。

OpenStand 对于 Google 来说,乃是性命之根本。试想,如果某个“封闭标准”的公司独占互联网哪怕是十分之一的内容,而且不开放内容给 Google 的爬虫(考虑一个充血版的 Facebook),那么搜索结果的质量会因此受到多大的影响?在这个普通网民都开始谈论“实时搜索”的时代,在底层(也就是通讯协议层)占据一个有利的位置(推出自己的开放标准,或者保证标准的开放性),对于 Google 这样的公司来说是一件多么重要的事?从这个角度来看,被事先高调宣布的 Google Wave 的 Open Source Product 和 Open Protocol 路线图,无论怎么看都是必须的一步棋。

Google Wave 不是实时 Web 应用的银弹

其实这是一句屁话——哪怕是在某个犄角旮旯的小不点儿领域,这个世界上也都从来就没有过什么银弹。我得承认,说“Google Wave 不是实时 Web 应用的银弹”,完完全全就是为了寻开心。一个软件老民工装出一副思想很深邃的样子,恶心一把装腔作势的软件砖家们,没办法,就是这么低级趣味。

首先,我也承认 Google Wave 眩得要命,客户方的代表看了也会喜欢得不得了,但它完完全全是基于 HTML5 标准的——你的意思是想去说服公司领导,让他们完全抛弃占据市场份额超过 80% 的广大 IE 浏览器用户么?XD,脑子笨一点不要紧,关键是不要进水就好了。

其次,我知道 Google Wave 提供了 Robots API 很多东西都可以“引入”到系统中,而利用 Gadgets API 又可以“展现”很多东西,况且 Google Wave 本身还会开源,哎呀,简直太好了,我们可以在 Google Wave 上架构我们的系统,既省钱来又省时间,这下终于有时间去泡妞了……。喂,醒一醒,XD。我们真的需要把我们的应用嵌入(接入) Google Wave 以获得 Realtime 特性,而不是相反?尤其是,当我们的应用并不像个 SNS 或者“协作系统”的时候也要如此?好吧,算你牛,非得这样,那,咱们项目组要不先回家待岗,等它出来了咱们再回来上班?

再还有,协作隐喻能够覆盖所有的 Realtime App 需求么?这是一个根本性问题,要不,咱再想想……?

干货上完,现在上水货。地址在[这里],各路水神水仙纷纷出动,精彩得紧。不要问我这水到底有多深,你自己下去探探不就知道了。;)

misc

他山之玉,以及其他

May 26th, 2009 :: jackyz

他山之玉

活跃于 .NET 技术圈的老赵同学,最近写了一个不错的文章系列——《一个轻量级Actor模型实现》。关于 ActorModel 可以参考《 Erlang Programming 》第七章 “并发” (98页)中的形象描述,也可以参照 Wikipedia 上 ActorModel 词条的严谨定义。

简而言之,所谓的 ActorModel 其本身的概念是极简单的,它只有两个基本的要素:每个 Actor 顺序地处理消息,多个 Actor 并发地执行。应该说,它是结构复杂(尤其是并行)应用程序的一种合理抽象。Joe Armstrong 在他的《 Erlang Programming 》第七章 “并发” 中认为:ActorModel 是从并发角度对人类社会的交互和协作行为进行模拟的结果。而在实际运用中,这一抽象模型,也早已广泛运用,其中的一些,我们还相当熟悉,比如:*nix 的进程和管道系统、 Email 系统、所有的 MQ 中间件,等等。作为抽象模型的 ActorModel ,它并不局限于某种特定的语言。换言之,采用任何一种语言(或者技术)都可以实现自己的 ActorModel 。

老赵以 .NET 实现的 ActorModel 原型,在基本特性上,已经具备了 ActorModel 的要素,细节可能仍有优化的余地。作为他自己独立思考和深入思辨的产物,不仅是对 .NET 技术领域的同学具有学习价值,对于 Erlangor 而言,因为他的模型是以 Erlang 作为样本的,而他实现过程的思辨,也给我们提供了相当独特的角度,反过来,对于我们理解 Erlang 本身的特性(为什么 Erlang 会被设计成这个样子),也很有帮助。

如下几个问题,建议 Erlangor 们在阅读老赵的文章时,顺便想想:

  • Erlang 的轻量级线程与 ActorModel 的任务调度有何关系。
  • Erlang 的动态类型+模式匹配方案和 ActorModel 的消息处理有何关系。
  • ActorModel 和 Singleton 以及 Lock-Free 又有何关系。

感谢 xushiwei 的 twitter 投递。

其他

以下是 blah 部分,含水量极高,请部分读者自行无视。

国内的 Erlang 应用进入“低调务实”阶段?

  • sohu 最新推出的 SNS —— “白社会”,使用 MochiWeb 作为 update notify 的 server 。打开 firebug 的 net 面板,很容易就能发现这一点(有请 sohu “白社会”的同学出来介绍一下详细情况)。
  • litao.cheng 同学在某公司也采用了 MochiWeb + erlang … 来实现某统计业务。
  • yufeng 同学在某公司采用 Erlang 实现动态集群。
  • xushiwei 同学在某公司采用 C 来实现 Erlang 的某些特性,据说效果不俗。
  • ……

再搞 Erlounge CN 的话,肯定会大有可观。

推荐阅读《Unix 编程艺术》

这一本书说起来是久闻大名,我却中了网络评论的毒,以为它是“拜 Unix 教”的《转X轮》或者是 Linux 老愤青 YY 的《中国不高兴》,所以一直也都没想过要找来看看。

某日,终于还是在图书馆(图书馆好地方啊)的一个书架前相遇了。随手抽出来翻了一下,本来准备扫一眼就放回去的,没想到就此读了一个下午,几乎到了让人放不下来的地步。相见恨晚啊。

尤其是书的第六章,作为一个 Erlangor 来说,共鸣尤为强烈。之前,总听人说 Erlang 的内部构造很象是一个 Unix 系的操作系统,这话听得多了,却总没什么感性认识,直到看了这本书,才觉得说得千真万确。

这种相似性,不只是体现在部分模块的命名/设计和很多思想的一脉相承上,更体现在 KISS 和以数据为核心的价值取向上。Erlang 的整个运行系统就好象是一个为并发进行过增强之后了的 Unix 系统(尤其是进程子系统和进程间通讯子系统),运行在它之上的程序就好比是 shell/perl 的脚本,以简单而强大的方式,通过由若干个彼此通讯的进程组成的计算网络来完成任务。

从这个角度,说 Erlang 是 Unix 核心思想朝并发方向的延伸和进化,并非只是 Erlangor 一厢情愿地想“往 Erlang 脸上贴金”的说法。

顺便查了一下这本书在 douban 上的评价,吃惊的发现进行过推荐的牛人严重扎堆。鄙视一下自己的火星。

关于 Concurrent Programming in Erlang Part2

知名的《Concurrent Programming in Erlang》一直都只在 Erlang.org 开放了 Part1 供大家免费下载,它的 Part2 因而充满了种种神秘的色彩。为了揭开这个谜底,我上次特地跑到“国家图书馆”外文阅览室,费了牛鼻子劲,终于将这本很可能是全中国唯一的一本,弄将出来瞧上了一瞧。下面是观感:

原来这本书的 Part2 内容比较杂,每个部分的篇幅内容也比较少,还略显有点过时(肯定的,是1996年出的,已经13年过去了)。尤其是其中讲 Database 的部分,似乎彼时连 Mnesia 都还没有成形,还有讲 GUI 的部分,使用也很少。其中的大部分内容,在网上都能找到其他的论述文章。可能唯有第 12 章 Operating Systems 的内容(也就是上述“Erlang OS 很象 Unix”的观点)似乎还没有看到相应的资料(知道的同学请补充之)。好在这部分内容关注的是 Erlang 的内部构造,它的缺失想必也不会太多的影响到大家的使用,所以关系应该不大。

情况就是这样子,貌似各位不需要惦记了。

misc

Erlang Factory 2009 Videos

May 20th, 2009 :: jackyz

Erlang Factory 大概算得上是 Erlang 世界在瑞典之外规模最大的会议了。之前在美国加州举办的 Palo Alto 为期两天,日程满满,好话题多到让人眼晕。这次 Erlang Factory 2009 – Palo Alto 放出了一堆好视频,地址在[这里](谁知道 PPT/PDF 在哪里可以看到?请跟帖分享之)。英国 London 在 6月22日到6月24日还会有另外一场欧洲 Base 的 Erlang Factory 不知道社区里面会不会有人参与其中呢?

misc

couchdb style offline storage?

May 9th, 2009 :: jackyz

Mozilla Labs 的 Atul Varma 发表了一篇博文[看这里],探讨使用一个浏览器内置的类似 CouchDB 的系统[看这里]来作为浏览器离线存储方案的可能。——于无声处闻惊雷!我得说,这真是一个天才的点子。

提起目前的 SqLite 方案,说实话,这的确是一个由 “直接神经传导” 产生的 “拿来主义” 方案(简而言之,就是说它很直观啦),而且确实可用。但,恐怕也很难有人能够再想出一个比 “在浏览器中使用 SQL ” 更让人昏昏欲睡的主意来了。就这一条,原本看起来还 “飘出未来的气味” 的浏览器开发,一个激灵,就能让人感觉出逼人的 “幽幽古意” 来。

本该如此,浏览器从来都是 JavaScript 的天下。一切设施都围绕 JavaScript 而存在,存储也不应该例外。这里的 CouchDB 其实和 Erlang 无关,它只是一个 “风格供应商” 而已。顺带的,如果在统一 Online/Offline 存储接口(这是 W3C 的问题) 之后要提供存储/同步服务(这是 Google 之类的问题) ,只有到了这个时候,才没准会有 CouchDB 的事(如果没有更好的替代的话)。但,创意真的是一个具有美感的东西。不是么?

唯一的疑惑是,我也知道 CouchDB 很久了,为什么就没有想到这个用法呢?

感谢 “力” 的投递,感谢 “zly06” 的推荐。

misc

[转] couchdb 上手指南

May 6th, 2009 :: jackyz

张沈鹏同学写了一篇不错的 couchdb 上手指南,以 wiki 格式发在 erlang-china 的 maillist 里。这里整理了一下格式,原文转贴出来,并郑重推荐之。

启动

balin couchdb #  ./utils/run

参数有

-h display a short help message and exit
-V display version information and exit
-a FILE add configuration FILE to chain
-A DIR add configuration DIR to chain
-n reset configuration file chain (including system default)
-c print configuration file chain and exit
-i use the interactive Erlang shell
-b spawn as a background process(作为后台进程)
-p FILE set the background PID FILE (overrides system default)
-r SECONDS respawn background process after SECONDS (defaults to no respawn)
-o FILE redirect background stdout to FILE (defaults to $STDOUT_FILE)
-e FILE redirect background stderr to FILE (defaults to $STDERR_FILE)
-s display the status of the background process
-k kill the background process, will respawn if needed
-d shutdown the background process(关闭)

配置

balin couchdb # vi etc/couchdb/local_dev.ini

可以指定端口号等,常用的有:

[httpd]
port = 12345
bind_address = 0.0.0.0

[admins]
用户名 = 密码

使用

http://123.123.123.123:12345/_utils/

可以创建数据库

python 中的使用

http://123.123.123.123:12345/_utils/database.html?python-tests

以操纵这个数据库作为演示,python库有几个函数比如update([...])不能用,不能用用户名密码等等,也许要修一下…

from couchdb import client
from couchdb.client import Document
server = client.Server('http://123.123.123.123:12345/')
 
#打开数据库
db = server['python-tests']
 
#创建一条数据
doc_id = db.create({'type': 'Person', 'name': 'John Doe'})
 
#获取一条数据,这个doc接口和字典一样
doc = db[doc_id]
 
#_rev是版本,_id是uuid
doc.items()
[(u'_rev', u'1-2963977070'),
(u'_id', u'4a36f238f4facbe08762b1a958cef39e'),
(u'type', u'Person'),
(u'name', u'John Doe')]
 
#可以自己指定主键
db['JohnDoe'] = {'type': 'person', 'name': 'John Doe'}
 
db['JohnDoe'].items()
[(u'_rev', u'1-2744716443'),
(u'_id', u'JohnDoe'),
(u'type', u'person'),
(u'name', u'John Doe')]
 
#更新
badman = db['JohnDoe']
badman[age]=1234
db['JohnDoe'] = badman
 
#删除,可以用db.delete(doc)来删除
del db['JohnDoe']
 
#遍历
for row in db.view('_all_docs'):
  
print row.id
 
#看数据库信息
db.info()
{
u'compact_running': False,
u'db_name': u'python-tests',
u'disk_size': 24381,
u'doc_count': 13,
u'doc_del_count': 0,
u'instance_start_time': u'1241518867280531',
u'purge_seq': 0,
u'update_seq': 21}
 
#文档可以有2进制的附件 put_attachment 用这个函数上传
# 查询,map_fun是一个js函数,emit是emit(key,value)。key,value均可是null
# web页面上有Select view查询,可以直接搜索测试
# 好像要用unicode字符 不然找不到 囧啊
 
db['/logo/xxx1.jpg']={"type":"logo","size":1}
db['/logo/xxx2.jpg']={"type":"logo","size":2}
db['/logo/xxx3.jpg']={"type":"logo","size":3}
db['/logo/xxx4.jpg']={"type":"logo","size":4}

Map函数

map_fun = u'''
function(doc) {
   if (doc.type=='logo')
       emit(doc._id, doc.size);
}
'''
 
for row in db.query(map_fun):
  
print row

输出

<Row id=u'logo/xxx1.jpg', key=u'logo/xxx1.jpg', value=1>
<Row id=u'logo/xxx2.jpg', key=u'logo/xxx2.jpg', value=2>
<Row id=u'logo/xxx3.jpg', key=u'logo/xxx3.jpg', value=3>
<Row id=u'logo/xxx4.jpg', key=u'logo/xxx4.jpg', value=4>

我们还可以加上reduce函数,比如:

  1. reduce_fun = u'''
  2. function(keys, values, rereduce) {
  3.    return sum(values)
  4. }
  5. '''
  6. for row in db.query(map_fun,reduce_fun):
  7.    print row

输出

<Row key=None, value=10>

reduce 中 rereduce变量的含义如下

  1. rereduce为false
    • key为array,element为:[key,id],key为map function产生的key,id为Document对应id
    • values为array,elements为map function产生的结果
    • 比如 reduce([ [key1,id1], [key2,id2], [key3,id3] ],[value1,value2,value3], false)
  2. rereduce为true
    • key为null
    • values为array,element为前一次reduce返回的结果
    • 比如reduce(null, [中间结果1,中间结果2,中间结果3], true)

[这里]有一些map/reduce演示的例子,比较好懂.

Creating Views
View 可以理解为索引了 不过这个索引不是实时的…
接着上文的例子

db["_design/test"]={
 
"views":
 
{
  
"all": {
    
"map": "function(doc) { if (doc.type == 'logo')  emit(null, doc) }"
  
},
  
"size_large_than_2": {
    
"map": "function(doc) { if (doc.size && parseInt(doc.size)>2)
emit(null,doc) }
"
  
},
  
"total_size": {
    
"map": "function(doc) { emit(null,parseInt(doc.size)) }",
    
"reduce": "function(keys,values) { return sum(values) }"
  
}
 
}
}

然后刷新

http://123.123.123.123:12345/_utils/database.html?python-tests

可以看到 select views中多了test,也可访问:

http://123.123.123.123:12345/python-tests/_design/test/_view/all

可以加上limit这一类参数

http://123.123.123.123:12345/python-tests/_design/test/_view/all?limit=2
http://123.123.123.123:12345/python-tests/_design/test/_view/all?limit=2&skip=1

这样可以分页,不过[这里]提到

A simpler method of doing this is to use the skip parameter to work out the starting document for the page, however this method should be used with caution. The skip \parameter simply causes the internal engine to not return entries that it is iterating over. While this gives the desired behaviour it is much slower than finding the first document for the page by key. The more documents that are skipped, the slower the request will be.

所以最好配合下面的startkey之类的来用skip
类似参数还有:

  • 排序 descending=false
  • 开始结束 startkey=”abc”&endkey=”abcZZZZZZZZZ” 可以用 docid startkey_docid=null
  • 合并结果 group=true 用法有点复杂,可以看[这里]

key可以是复杂的key,比如:

The query startkey=["foo"]&endkey=["foo",{}] will match most array keys with “foo” in the first element, such as ["foo","bar"] and ["foo",["bar","baz"]]. However it will not match ["foo",{"an":"object"}]

python中可以这样访问

for row in db.view('_design/test/_view/all'):
  
print row.id

输出

logo/xxx1.jpg
logo/xxx2.jpg
logo/xxx3.jpg
logo/xxx4.jpg

又如

for row in db.view('_design/test/_view/size_large_than_2'):
  
print row

输出

<Row id=u'logo/xxx3.jpg', key=None, value={u'_rev': u'1-3347158087',
u'_id': u'logo/xxx3.jpg', u'type': u'logo', u'size': 3}>
<Row id=u'logo/xxx4.jpg', key=None, value={u'_rev': u'1-1107796651',
u'_id': u'logo/xxx4.jpg', u'type': u'logo', u'size': 4}>

网络资源

  1. 根据网上的测试表明:couchdb 写入速度 比 mysql 慢4倍,创建索引速度 比 mysql 慢50倍
  2. couchdb 只写入不删除,需要定期做整理,类似垃圾回收的copy+删除,需要预留大量磁盘空间.
  3. 索引不是实时的,你可能看到的是旧的数据

我的个人看法
单单看性能,couchdb的确很不理想,但是couchdb可以把数据以view的方式展现,要什么,就新建什么样的view,这种随心所欲索引方式,在不少应用的场合,通过view的方式把这种查询结果持久化,可以大大减少了把传统意义上的重复且相似查询.

study

[荐]talk to erlang in ruby with Erlix

April 29th, 2009 :: jackyz

KDr2(Killy Draw)同学做了一个 Ruby – Erlang 的项目 Erlix 。象这种富有新意(Talk to Erlang as A Node 而不是 as A Port, Like erlectricity)的民族软件(KDr2 Speaks Chinese),而且文档也比较完整,实在是找不出不大力进行推荐的理由。

项目主页:http://code.google.com/p/erlix/ || http://github.com/KDr2/erlix/

代码下载:http://erlix.googlecode.com/files/erlix-0.2.zip

使用教程:http://code.google.com/p/erlix/wiki/ErlixTutorial

另外,还有买一赠一惊喜大特惠!这里再推荐一篇通过 Erlang Node 机制进行通讯的原理性文章(刚巧也是 Ruby 的),如果想要实现一个自己的 Talk to Erlang as A Node in xxx Language (貌似好几个语言都已经有了自己的版本,大家动手之前,先 google 一下,看看别人做了没有),相信这一篇 [ 点这里 ] 也会很有参考价值。

news