Documentation

Posted on

Documentation

JavaScript Cookie Handling Library and jQuery plugin

Project Home Downloads Wiki Issues Source Search Search within: All wiki pages Featured pages Current pages Deprecated pages for

Documentation

How to use jquery.cookies.js Featured

Updated Jan 13, 2010 by auldrid...@gmail.com

How to use jquery.cookies.js

Without jQuery

If jQuery is not available in your page, the core cookies library is available to you under the jaaulde.utils namespace:

/// / get - get one, several, or all cookies / / @access public / @paramater Mixed cookieName - String:name of single cookie; Array:list of multiple cookie names; Void (no param):if you want all cookies / @return Mixed - Value of cookie as set; Null:if only one cookie is requested and is not found; Object:hash of multiple or all cookies (if multiple or all requested); // get = function(cookieName)

Example:

  • jaaulde.utils.cookies.get('myCookie');

  • returns value of myCookie if it is present, null if not

  • jaaulde.utils.cookies.get(['myCookie', 'myOtherCookie']);

  • returns array containing value of each requested cookie if it is present, null if not

  • jaaulde.utils.cookies.get();

  • returns array of all cookies from your site

Get Filtered list of cookies

/// / filter - get array of cookies whose names match the provided RegExp / / @access public / @paramater Object RegExp - The regular expression to match against cookie names / @return Mixed - Object:hash of cookies whose names match the RegExp // filter = function( cookieNameRegExp )

Example:

  • jaaulde.utils.cookies.filter( /^site/ );

  • returns list of cookies whose names start with "site"

/// / set - set or delete a cookie with desired options / / @access public / @paramater String cookieName - name of cookie to set / @paramater Mixed value - Any JS value. If not a string, will be JSON encoded (http://code.google.com/p/cookies/wiki/JSON); NULL to delete / @paramater Object options - optional list of cookie options to specify / @return void // set = function(cookieName, value, options)

Example:

  • jaaulde.utils.cookies.set('myCookie', 'myValue');

  • sets cookie by the name of 'myCookie' to value of 'myValue' with default options

  • jaaulde.utils.cookies.set('myCookie', 'myValue', {path: '/somedir'});

  • sets cookie by the name of 'myCookie' to value of 'myValue' with path of '/somedir'

  • See information on options object below

/// / del - delete a cookie (domain and path options must match those with which the cookie was set; this is really an alias for set() with parameters simplified for this use) / / @access public / @paramater MIxed cookieName - String name of cookie to delete, or Bool true to delete all / @paramater Object options - optional list of cookie options to specify ( path, domain ) / @return void /*/ del = function(cookieName, options)

Example:

  • jaaulde.utils.cookies.del('myCookie');

  • deletes a cookie, 'myCookie', with default options

  • jaaulde.utils.cookies.del('myCookie', {path: '/somedir'});

  • deletes a cookie by the name of 'myCookie' which had been set with a path of '/somedir'

  • jaaulde.utils.cookies.del(true);

  • deletes all cookies

  • A cookie can only be deleted using the same options with which it was set

  • See information on options object below

Test if browser is accepting cookies

/// / test - test whether the browser is accepting cookies / / @access public / @return Boolean /*/ test = function()

Example:

  • jaaulde.utils.cookies.test();

  • attempts to set a cookie and returns true or false upon success or failure

Set default options to use when none are specified

/// / setOptions - set default options for calls to cookie methods / / @access public / @param Object options - list of cookie options to specify / @return void // setOptions = function(options)

Example:

  • jaaulde.utils.cookies.setOptions({path: '/somedir'});

  • all cookies will be set or deleted with the path , '/somedir', unless it is explicitly provided in a passed options object

  • See information on options object below

With jQuery

If jQuery is available, then all of the above methods are available to you under the jQuery.cookies (or $.cookies ) namespace:

  • $.cookies.get()
  • $.cookies.filter()
  • $.cookies.set()
  • $.cookies.del()
  • $.cookies.test()
  • $.cookies.setOptions()

In addition, there are some jQuery function additions for helping automate some cookie tasks:

  • Set the value of a form field or the HTML of an element to a cookie named after the field's/element's name or id attribute

  • $('/#username').cookify();

  • The value of the field, or HTML of the element, with id "username" is set to a cookie named after the name or id attribute of that field/element. If a radio or checkbox and it's checked, the value will be set.

  • Fill a field's value, or an element's innerHTML with the value of a cookie

  • $('/#username').cookieFill();

  • Set the value of the input, or HTML of the element, with id, 'username', to the value of a cookie by the same name. If a radio or checkbox and it is checked, the cookie will be set. If not checked, the cookie will be deleted.

  • Bind an input to the cookies library

  • $('/#username').cookieBind();

  • Fills the field or element with id, 'username', with the cookie named the same and sets the field's/element's change event to fire cookify() to update the cookie when the input value changes

Options object

Using the options object, cookies can be set with several options such as the domain and or path for which the cookie should be available, expiration date for the cookie, and whether the cookie should be sent over HTTPS only.

The options object has four properties:

  • domain

  • STRING

  • For which domain should the cookie be available

  • path

  • STRING

  • For which path should the cookie be available

  • hoursToLive (DEPRECATED for expiresAt)

  • NUMBER

  • For how many hours should the cookie be valid? (Passing 0 means to delete the cookie at the end of the browser session--this is default. Negative values will delete the cookie, but you should use the del() method instead.)

  • expiresAt

  • Date OBJECT

  • Date object representing expiration date/time of cookie

  • secure

  • BOOL

  • Should cookie be sent to server via HTTPS only?

The structure of the object is as follows: var newOptions = { domain: '/*.mydomain.com', path: '/somedir', expiresAt: new Date( 2011, 1, 1 ), secure: true }

You need only set those options which you desire to override.

The default options when not overridden are:

  • domain

  • no value - will cause current domain of current page to be used

  • path

  • /

  • expiration

  • no value--causes cookie to be deleted at end of browser session

  • secure (send over HTTPS only)

  • false

An options object can be passed with set(), del(), cookify(), and cookieBind() to override the defaults on a case by case basis. You can also pass an options object to setOptions() to override the defaults for all calls.

IMPORTANT NOTE: Cookies must be deleted using the same domain and path options with which they were set. Else the cookie will not delete. This is just how cookies work.

构架师已死

Posted on

构架师已死

您还未登录!|登录|注册|帮助

方剑斌

不送不迎 真君子自来去 无晴无雨 大丈夫何逍遥

构架师已死

分类: 随笔 2006-06-12 00:24 8291人阅读 评论(33) 收藏 举报 工作strutsspring面试教育框架

2006年的职场出奇的冷清,相比前几年,简历的数量和质量都大为不如,很难得找到三年工作经验以上的人,有一个不是特别笨,就是特别怪。就是么,干得好谁没事换工作啊!Simon是一家外企软件公司的总经理,最近给这个问题愁坏了。项目一个接一个的接下来,人手越来越紧张。虽然Simon是个极限编程的粉丝,但也不得不批准了一份又一份的加班申请。HR经理把这个问题归结到房价上,他的妙论是“怕失业了还不上房款,不敢跳槽”。

这天,K项目组长Allen终于忍不住了,带了一个只有一年工作经验的小伙子要Simon面试,“很聪明!经验少了点。”

Simon皱了皱眉毛,说:“你不知道这个职位最低要求是三年工作经验吗?”

Allen说:“这已经是三个月里通过技术考试中最好的一个了,老大,试试吧。”Allen是Simon多年的哥们,比较随便。

抵到面子上来,Simon只好让Allen把小伙子带进来。

Simon的面试通常是三步曲:

问题一:你能说说毕业后的主要工作经历吗?

问题二:再说说你在公司的地位?

问题三:你的发展目标是什么?等回答后,比如说构架师,他就跟着问:想象一下你当构架师的一天,说给我听听?

小伙子回答第一问题很快很清楚,一年工作当然没什么东西。Simon觉得小伙子挺聪明。所以在小伙子回答了第二个问题后,问了一个发散性的问题:“你刚才说你在公司里处于中等水平,那比你差的人为什么会比你差呢?”

这个问题是个陷阱。

小伙子冒冒失失回答说:“我觉得他们每天工作是为工作而工作,工作没有责任感。”

Simon点点头说:“是吗?那真是糟糕的员工。那你刚好比糟糕的员工好一点了?”

小伙子的脸一下子红了,“我不是这个意思……”

“好了,那你说说比你好的人为什么比你强?”

“我觉得他非常努力,工作很多年了还在学习各种构架,水平很高。”于是Simon就问那最后一个问题。果然,小伙子回答的是要成为构架师。大概70%的人想成为构架师。但是构架师是什么呢?

Simon问道:“那你为什么要成为构架师呢?”

小伙子一愣,大概还没有人这么置疑过他。“年纪大了,不能老写程序吧。”这个回答,让Simon想起关于他对什么是老的定义:当你希望做年轻人做的事情时,你就还年轻;如果你希望做老年人做的事情,你就老了。这和你出生了多长时间是没有关系的。

Simon接着问:“好吧,那你说说你成为构架师以后,每天都会做什么?”

小伙子说:“我还没想过,不过,我想应该主要是需求分析,设计构架吧……”这大概是现在年轻人的通病,年轻人很容易追逐一些自己也不清楚的目标。

Simon问:“那设计构架具体都做些什么呢?”

小伙子这次的回答是:“比如,选择程序框架,决定用Spring或Struts等等。”

“哦,那我问你,你怎么说服别人是用Spring还是Struts呢?”

“如果我有经验,我会知道哪个更好……”

“是吗,但关于Spring或Struts的知识任谁都可以很容易得到。如果别人不同意你的建议,你怎么说服他?如果同意你的建议,那你不过是作出了和别人一样的认识,别人又凭什么认可你呢?”

小伙子没想过构架师日子里还有一个说服人的工作,说:“我是构架师,我应该有权力做决定吧?”

Simon想起权力的三种层次,第一层,任命;第二层,专业;第三层,品德。

Simon问:“如果在一个成熟的软件企业里没有你所想象的构架师呢?或者说,构架师这种职业已经死亡或消失了呢?你会怎么定位你的职业?”

小伙子显得很震惊。

Simon画了一个系统构架,然后又给小伙子看了一段代码。

“那一个更难懂?”Simon问。

小伙子指着代码说:“代码难懂。”

Simon的解释是:“这就是为什么实际上所谓的构架师不存在的原因。一个更简单的东西怎么会更有价值呢?每个人都能够画出这种构架图,但不是每个人都能写出好的代码。”

送走了小伙子,Simon有点难受。他有点喜欢这个小伙子,但是,这又是一个被愚蠢的教育和误人子弟的技术杂志污染的家伙。Simon在自己的笔记本中加了一句话:中国程序员最愚蠢的认识之三:我想当构架师。前面两个赫然是:

35岁后写不动程序了;

我只要做Java(C++); 分享到:

32楼 dongtianlaile 2010-11-08 10:14发表 [回复] [引用] [举报]我想问一下:为什么“我只要做java(C++)”是三个最愚蠢的认识之一呢? 很多人接触了java,就不想去做C++了,专心做java ,争取在这方面成为专家,有什么不好?难道比较牛的人就要对java和C++都很精通吗?31楼 jiayajun88 2007-12-12 09:27发表 [回复] [引用] [举报]当一个架构师也想过,但我想那是个漫长而艰辛的过程,我眼下就是要先做一个合格的JAVA程序员!!!!30楼 ilovegnu 2007-04-29 14:15发表 [回复] [引用] [举报]我认为能真正把coding做 “好”了,自然就是架构师了;如果每天的coding都只是为了完成工作而做的代码的堆积,那么确实是越老越不值钱,自以为经验很多,其实离架构师越来越远了。29楼 afxcn 2007-04-27 21:44发表 [回复] [引用] [举报]我就要当架构师 而且我会为这个目标奋斗不已28楼 鼠标 2006-10-16 12:03发表 [回复] [引用] [举报]我觉得故事里的小伙子没什么错,只是年轻经验不足而已。
我觉得小伙子想法很正确,大家都这么想,只是不是仅仅想就能做好而已。追求一个更美好的未来有什么错?人人都有这个想法,不说才是真的虚伪和不诚信。
这文章写的像“劝善文”......27楼 魔芋 2006-10-15 20:51发表 [回复] [引用] [举报]中国不需要更好的软件26楼 zelision 2006-10-09 11:05发表 [回复] [引用] [举报]一直关注大师的文章,支持!
当经济条件物质生活已经到了一定的层次,即使不用拼命的工作也能让自己和家人过得更好的话,我想会有更多的人去坚持自己的信念走一条自己永远有着自己思想和属于自己的路吧
虽然有点理想化了点,但还是觉得不错!25楼 albertlee 2006-09-07 00:45发表 [回复] [引用] [举报]写的好啊,估计楼上几位也应该听说过 alienbat 亡灵法师的大名吧~ 呵呵24楼 beggar 2006-07-16 10:35发表 [回复] [引用] [举报]找工作最不幸的就是碰上这种高高在上自以为是急功近利的主了,好的架构师必然是一个优秀的程序员,反之亦然,不过一般是从程序员到架构师的过程,架构师必须有编码的功底。系统构架设计出来自然就比较容易看懂,就象整体的战略总比局部的丛林容易明白一样,问题在于对各种部件的准确把握以及自身团队资源的充分了解才能做出近优的设计,招人重要的是看他能不能胜任工作和发展潜力,而不是看别人的人生观是否和你一致23楼 Sean.Pu 2006-06-19 10:56发表 [回复] [引用] [举报]如果你认为他聪明,可以给予一定机会嘛.从管理的角度来看,他才毕业一年也许很多东西都没有想到.22楼 ballzhi 2006-06-15 17:13发表 [回复] [引用] [举报]构架师价值就好比 战场上将军和小兵的价值对比,不想当将军的士兵不是好士兵, 不过最有价值的还是做管理的皇帝21楼 ballZhi 2006-06-15 17:05发表 [回复] [引用] [举报]姑且不论简单的东西有没有价值,但把复杂的需求变成"简单"的东西的这种能力,就很有价值,20楼 BlueDog 2006-06-14 21:15发表 [回复] [引用] [举报]虽然我们想做一辈子技术,但世俗会充许么
也许我们会屈服于世俗,但却迷失了自我。
做个快乐的Coder或者是迷茫的管理者在中国于每个做技术的人都是个问题?
传统文化告诉人的终极目标是物质世界权力颠峰而不是内心世界的精神领袖19楼 sanniko 2006-06-13 13:15发表 [回复] [引用] [举报]35岁,你的老板会怎么考虑你的地位呢??你想做技术,但老板不想再给你钱。我认为是这样.现在很多老板都觉得技术很简单,大学生遍地都是,随便招几个就可以。18楼 哈哈 2006-06-13 11:11发表 [回复] [引用] [举报]中国有几本技术杂志,哈哈,<<程序员>>??17楼 Shica 2006-06-13 00:55发表 [回复] [引用] [举报]虽然有点偏激,但也指出了目前大部分IT人员的盲目与浮躁,一针见血。
架构与编码,关注的面不同,所处的抽象层次也不同,其实也很难做什么比较。16楼 匿名路过 2006-06-13 00:52发表 [回复] [引用] [举报]这篇文字原来是说:只构架不写代码的人已经没有出路了。。。
倒是我一直认同的,现在的java的声势,造就了太多夸夸其谈的人和名词
很多在c/s里用的很平常的做法,到了java上就是一个脍炙人口的创新概念,直到由于java本身的限制,导致新概念的实际应用效果实在太差而不得不被淘汰
对于那个小伙子的被淘汰,觉得有点不公平:人家才工作几年,就要他有这样的想法,现实吗?再说,现在招他,应该也不会让他现在就做架构师啊。。。15楼 匿名路过 2006-06-13 00:44发表 [回复] [引用] [举报]能让你们在每个大的版本都会可以在安全、性能、扩展性的诸多细小方面做构架上的改良的原始架构,应该也就是一个不错的框架了吧
否则,早就在某个版本被彻底抛弃了14楼 cunruizhai 2006-06-13 00:16发表 [回复] [引用] [举报]Fasion, 谢谢你的回话。
我所言的构架师已死,很大程度上指那些只构架不写代码的人已经没有出路了。程序的构架仍然至关重要。只是构架的形成不应该是非常早期就形成,而是逐步逼进。这也是我这些年的体会。我们的一个产品,由于非常庞大(800人的项目),几乎每个大的版本都会在安全、性能、扩展性的诸多细小方面做构架上的改良。几个版本后,找到了最原始的构架设计,竟然哑然失笑!因为已经完全不同了。有时候,和同事讨论的时候,说,是否有人可能在第一时间就设计出完美的构架,以后就不需要改了呢?大家一致认为,这是Mission Impossible,明天说不定就会来一个你完全没想到的漏洞。后来看了敏捷的一些概念,特别是设计已死那篇文章,刚好听到这个故事,就随手写了一篇。13楼 fasiondog 2006-06-12 23:08发表 [回复] [引用] [举报]你好,看了你的留言,一时来不及写东西,先来回个话:-)
你的观点我不完全赞同,赞同的是最愚蠢的3个认识(“我要做架构师”让我想起了小时候,“我要做科学家”的豪情壮语),不过“架构师已死”我不能完全赞同。
写篇文章真的好累(不知是否有同感),一时我还写不出来,过几日我把我的看法写出来一起讨论。
另外,你的文章很有特色,很棒!(其实你的文章我已经看过,本要使用我的推荐权,可是最近一直无法显示推荐时的验证码,郁闷中)12楼 iqueen 2006-06-12 21:13发表 [回复] [引用] [举报]结尾没有看懂!11楼 LucasLee 2006-06-12 17:09发表 [回复] [引用] [举报]不错的文章!10楼 bigfanofcpp 2006-06-12 17:06发表 [回复] [引用] [举报]中国程序员最愚蠢的认识之三:
我想当构架师。

前面两个赫然是:

35岁后写不动程序了;

我只要做Java(C++);

这个。。。。。。客观的说恐怕不光是个人原因吧。

9楼 bigfanofcpp 2006-06-12 17:03发表 [回复] [引用] [举报]可悲!
8楼 nlhlx 2006-06-12 12:22发表 [回复] [引用] [举报]山高月小,水落石出,好的程序员象是山中修炼道士,要化长时间修炼,要耐得住寂寞.水滴石穿之时,大功告成.
newxy技术就是这样炼成的.http://www.newxy.net7楼 joshyupeng 2006-06-12 10:50发表 [回复] [引用] [举报]自从比尔该死当上架构师之后,所有人都想当架构师了。真正伟大的是架构师手中的砖瓦,而不是架构师本人。
6楼 tototo 2006-06-12 09:50发表 [回复] [引用] [举报]团队中的真正高手最大的能力是把复杂的事情分解成简单的部分,工作分解才方便。

而把任务变复杂的人,看起来很NB,个人素质高,但在团队合作中只能当研发人员,根本不可能胜任带管理性质的工作。5楼 walkman 2006-06-12 09:34发表 [回复] [引用] [举报]编得吧?真正的架构可不是用spring还是strut这么简单,架构要要考虑系统的方方面面,好的编程功底是基础,我见过好的架构师思维能力不是一般的强,只能说你们公司的架构师太水了4楼 wxfy1977 2006-06-12 10:21发表 [回复] [引用] [举报]有点道理3楼 匿名路过 2006-06-12 09:17发表 [回复] [引用] [举报]35岁后写得动程序,而且还写的更好了
但是,收入、地位低得逼你放弃写程序
--这才是中国国情2楼 jiyucn 2006-06-12 09:07发表 [回复] [引用] [举报]"又是一个被愚蠢的教育和隔离误人子弟的技术杂志污染的家伙",这样人太多了1楼 jiyucn 2006-06-12 09:03发表 [回复] [引用] [举报]写得好,感触很多。 您还没有登录,请[登录][注册]

/* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场 TOP

个人资料

cunruizhai

  • 访问:289015次
  • 积分:3189分
  • 排名:第1981名

  • 原创:39篇

  • 转载:0篇
  • 译文:0篇
  • 评论:598条

文章搜索

文章分类

展开

阅读排行

推荐文章 最新评论

yin_wuzhe: 真不错,收藏..

linglingluoluo2010: 我最近也莫名奇妙多了好多关注着,名字都很相像,没有太在意,现在都不怎么玩新浪微博了,没有开始的新鲜劲...

编程难民: 说的好,太抠了,干的不爽,没事也想搞点事

suc_qq: 呵呵 真这样。我上个公司就这样。一样的

大智若愚: 务实!!!

liu344781071: 为啥?

31737951: 你把软件够架司的位置放到什么地方去了?提出意见要经过够架师再设计把?

yanmeixiangangel: 这是一种理念,实际还得根据公司的实际情况走的。对待不同的人都该有所区别。

waile23: 管理要从管事转变为管人,就是成功的开始了。

aflyeagle: 请问一个问题:“设立一个周评审机制,同时所有经理在另一个工具填数据,这样,人员统计就基本准确了。”这...

公司简介|招贤纳士|广告服务|银行汇款帐号|联系方式|版权声明|法律顾问|问题报告QQ客服 微博客服 论坛反馈 联系邮箱:webmaster@csdn.net 服务热线:400-600-2320京 ICP 证 070598 号北京创新乐知信息技术有限公司 版权所有世纪乐知(北京)网络技术有限公司 提供技术支持江苏乐知网络技术有限公司 提供商务支持Copyright © 1999-2012, CSDN.NET, All Rights Reserved GongshangLogo

JS URL传中文参数引发的乱码问题_javascript技巧_脚本之家

Posted on

JS URL传中文参数引发的乱码问题javascript技巧脚本之家

脚 本 之 家 www.jb51.net

脚本之家

JS URL传中文参数引发的乱码问题

发布:dxy 字体:[增加 减小] 类型:转载

今天的项目中碰到了一个乱码问题,从JS里传URL到服务器,URL中有中文参数,服务器里读出的中文参数来的全是“?”,查了网上JS编码相关资料得以解决。 解决方法如下: 1、在JS里对中文参数进行两次转码 复制代码 代码如下:

var login_name = document.getElementById("loginname").value; login_name = encodeURI(login_name); login_name = encodeURI(login_name); 2、在服务器端对参数进行解码 复制代码 代码如下:

String loginName = ParamUtil.getString(request, "login_name"); loginName = java.net.URLDecoder.decode(loginName,"UTF-8"); 在使用url进行参数传递时,经常会传递一些中文名的参数或URL地址,在后台处理时会发生转换错误。在有些传递页面使用GB2312,而在接收页面使用UTF8,这样接收到的参数就可能会与原来发生不一致。使用服务器端的urlEncode函数编码的URL,与使用客户端javascript的encodeURI函数编码的URL,结果就不一样。 javaScript中的编码方法: escape() 方法: 采用ISO Latin字符集对指定的字符串进行编码。所有的空格符、标点符号、特殊字符以及其他非ASCII字符都将被转化成%xx格式的字符编码(xx等于该字符在字符集表里面的编码的16进制数字)。比如,空格符对应的编码是%20。unescape方法与此相反。不会被此方法编码的字符: @ / / + 英文解释:MSDN JScript Reference: The escape method returns a string value (in Unicode format) that contains the contents of [the argument]. All spaces, punctuation, accented characters, and any other non-ASCII characters are replaced with %xx encoding, where xx is equivalent to the hexadecimal number representing the character. For example, a space is returned as "%20." Edge Core Javascript Guide: The escape and unescape functions let you encode and decode strings. The escape function returns the hexadecimal encoding of an argument in the ISO Latin character set. The unescape function returns the ASCII string for the specified hexadecimal encoding value. encodeURI() 方法:把URI字符串采用UTF-8编码格式转化成escape格式的字符串。不会被此方法编码的字符:! @ /# $& / ( ) = : / ; ? + ' 英文解释:MSDN JScript Reference: The encodeURI method returns an encoded URI. If you pass the result to decodeURI, the original string is returned. The encodeURI method does not encode the following characters: ":", "/", ";", and "?". Use encodeURIComponent to encode these characters. Edge Core Javascript Guide: Encodes a Uniform Resource Identifier (URI) by replacing each instance of certain characters by one, two, or three escape sequences representing the UTF-8 encoding of the character encodeURIComponent() 方法:把URI字符串采用UTF-8编码格式转化成escape格式的字符串。与encodeURI()相比,这个方法将对更多的字符进行编码,比如 / 等字符。所以如果字符串里面包含了URI的几个部分的话,不能用这个方法来进行编码,否则 / 字符被编码之后URL将显示错误。不会被此方法编码的字符:! /* ( ) 英文解释:MSDN JScript Reference: The encodeURIComponent method returns an encoded URI. If you pass the result to decodeURIComponent, the original string is returned. Because the encodeURIComponent method encodes all characters, be careful if the string represents a path such as /folder1/folder2/default.html. The slash characters will be encoded and will not be valid if sent as a request to a web server. Use the encodeURI method if the string contains more than a single URI component. Mozilla Developer Core Javascript Guide: Encodes a Uniform Resource Identifier (URI) component by replacing each instance of certain characters by one, two, or three escape sequences representing the UTF-8 encoding of the character. 因此,对于中文字符串来说,如果不希望把字符串编码格式转化成UTF-8格式的(比如原页面和目标页面的charset是一致的时候),只需要使用escape。如果你的页面是GB2312或者其他的编码,而接受参数的页面是UTF-8编码的,就要采用encodeURI或者encodeURIComponent。 另外,encodeURI/encodeURIComponent是在javascript1.5之后引进的,escape则在javascript1.0版本就有。 英文注释:The escape() method does not encode the + character which is interpreted as a space on the server side as well as generated by forms with spaces in their fields. Due to this shortcoming, you should avoid use of escape() whenever possible. The best alternative is usually encodeURIComponent().Use of the encodeURI() method is a bit more specialized than escape() in that it encodes for URIs [REF] as opposed to the querystring, which is part of a URL. Use this method when you need to encode a string to be used for any resource that uses URIs and needs certain characters to remain un-encoded. Note that this method does not encode the ' character, as it is a valid character within URIs.Lastly, the encodeURIComponent() method should be used in most cases when encoding a single component of a URI. This method will encode certain chars that would normally be recognized as special chars for URIs so that many components may be included. Note that this method does not encode the ' character, as it is a valid character within URIs.

Tags:url 中文参数 乱码 复制链接发给好友收藏本文打印本文关闭本文返回首页

上一篇:FF IE兼容性的修改小结

下一篇:Javascript 中介者模式实例

同类文章

文章评论

共有 **位脚本之家网友发表了评论我来说两句

最 近 更 新

关于本站 - 广告合作 - 联系我们 - 免责声明 - 网站地图 - 意见反馈 - 返回顶部

欢迎转载我们的原创作品,转载请注明出处。苏ICP备06043639号 Copyright © 2006-2010 www.jb51.net online services. All rights reserved. . QQ群1:14624678 QQ群2:36345889或业务QQ:461478385

FusionCharts FREE

Posted on

FusionCharts FREE - XML Structure

Candlestick Chart Specification Sheet SWF: FCF_Candlestick.swf A general XML document for the candlestick chart looks as under:

As you can see in the above XML document, there are basically four sections of data:

  1. section - This section helps you set the various visual attributes for the chart apart from a few other numerical attributes.
  2. section - This section of data lets you create the textual categories to be displayed on the chart. It also helps you configure the category vertical lines and their formatting.
  3. section - This is the actual section where you define your financial data.
  4. section - This section helps you set the trend lines on the chart.

Let's now see each of them in detail. Attributes of the element help you set the visual looks of the chart and a few functional parameters. Here we'll group those attributes by their parent chart element and then look at it.

Graph Properties

  • bgColor="HexColorCode" : This attribute helps you set the background color of the chart.
  • bgAlpha="NumericalValue(0-100)" : This attribute helps you set the alpha (transparency) of the graph.

Canvas Properties

  • canvasBgColor="HexColorCode" : This attribute helps you set the background color of the canvas.
  • canvasBgAlpha="NumericalValue(0-100)" : This attribute helps you set the alpha (transparency) of the canvas.
  • canvasBorderColor="HexColorCode" : This attribute helps you set the border color of the canvas.
  • canvasBorderThickness="NumericalValue(0-100)" : This attribute helps you set the border thickness (in pixels) of the canvas.

Chart Numerical Limits

  • xAxisMinValue="value" : This attribute determines the lower limit of x-axis.
  • xAxisMaxValue="value": This attribute determines the upper limit of x-axis.
  • yAxisMinValue="value": This attribute determines the lower limit of y-axis.
  • yAxisMaxValue="value" : This attribute determines the upper limit of y-axis. If you don't specify any of the above 4 values, it is automatically calculated by FusionCharts based on the data provided by you.
  • overRideLimitCalc="1/0": When you provide data and the upper and lower limits to FusionCharts, FusionCharts (while rendering) checks whether the upper and lower limits are correctly provided - that is it checks whether all the data values fall within the specified range. Sometimes, this process takes a little extra time when you have a large amount of data. If in that case you don't want FusionCharts to cross check the limits explicitly provided by you, you can set this attribute value to 1 and then FusionCharts won't delve into the process of checking thus saving that extra bit of time required.

Bars or Candles

  • showAsBars="1/0": Whether to show candles or bars on the chart.

Divisional Lines (Horizontal)

  • numdivlines="NumericalValue" : This attribute sets the number of divisional lines to be drawn.
  • divlinecolor="HexColorCode" : The color of grid divisional line.
  • divLineThickness="NumericalValue" : Thickness (in pixels) of the grid divisional line.
  • divLineAlpha="NumericalValue0-100" : Alpha (transparency) of the grid divisional line.
  • showDivLineValue="1/0" : Option to show/hide the textual value of the divisional line.
  • showAlternateHGridColor="1/0" : Option on whether to show alternate colored horizontal grid bands.
  • alternateHGridColor="HexColorCode" : Color of the alternate horizontal grid bands.
  • alternateHGridAlpha="NumericalValue0-100" : Alpha (transparency) of the alternate horizontal grid bands.

Divisional Lines (Vertical)

  • numVDivLines="NumericalValue" : Sets the number of vertical divisional lines to be drawn.
  • VDivlinecolor="HexColorCode" : Color of vertical grid divisional line.
  • VDivLineThickness="NumericalValue" : Thickness (in pixels) of the line
  • VDivLineAlpha="NumericalValue0-100" : Alpha (transparency) of the line.
  • showAlternateVGridColor="1/0" : Option on whether to show alternate colored vertical grid bands.
  • alternateVGridColor="HexColorCode" : Color of the alternate vertical grid bands.
  • alternateVGridAlpha="NumericalValue0-100" : Alpha (transparency) of the alternate vertical grid bands.

General Properties

  • caption="String" : Caption of the chart
  • subCaption="String" : Sub-caption of the chart
  • shownames="1/0" : Option whether to show/hide the category names.
  • showLimits="1/0" : Option whether to show/hide the chart limit textboxes.
  • rotateNames="1/0" : Configuration that sets whether the category name text boxes would be rotated or not.

Number Formatting Options

  • numberPrefix="$" : Using this attribute, you could add prefix to all the numbers visible on the graph. For example, to represent all dollars figure on the chart, you could specify this attribute to ' $' to show like $40000, $50000.
  • numberSuffix="p.a" : Using this attribute, you could add prefix to all the numbers visible on the graph. For example, to represent all figure quantified as per annum on the chart, you could specify this attribute to ' /a' to show like 40000/a, 50000/a. To use special characters for numberPrefix or numberSuffix, you'll need to URL Encode them. That is, suppose you wish to have numberSuffix as % (like 30%), you'll need to specify it as under: numberSuffix='%25'
  • formatNumber="1/0" : This configuration determines whether the numbers displayed on the graph will be formatted using commas, e.g., 40,000 if formatNumber='1' and 40000 if formatNumber='0 '
  • formatNumberScale="1/0" : Configuration whether to add K (thousands) and M (millions) to a number after truncating and rounding it - e.g., if formatNumberScale is set to 1, 10434 would become 1.04K (with decimalPrecision set to 2 places). Same with numbers in millions - a M will added at the end.
  • decimalSeparator="." : This option helps you specify the character to be used as the decimal separator in a number.
  • thousandSeparator="," : This option helps you specify the character to be used as the thousands separator in a number.
  • decimalPrecision="2" : Number of decimal places to which all numbers on the chart would be rounded to.
  • divLineDecimalPrecision="2": Number of decimal places to which all divisional line (horizontal) values on the chart would be rounded to.
  • limitsDecimalPrecision="2" : Number of decimal places to which upper and lower limit values on the chart would be rounded to.

Hover Caption Properties

  • showhovercap="1/0" : Option whether to show/hide hover caption box.
  • hoverCapBgColor="HexColorCode" : Background color of the hover caption box.
  • hoverCapBorderColor="HexColorCode" : Border color of the hover caption box.
  • hoverCapSepChar="Char" : The character specified as the value of this attribute separates the name and value displayed in the hover caption box.

Font Properties

  • baseFont="FontName" : This attribute sets the base font family of the graph font which lies on the canvas i.e., all the values and the names in the graph which lie on the canvas will be displayed using the font name provided here.
  • baseFontSize="FontSize" : This attribute sets the base font size of the graph i.e., all the values and the names in the graph which lie on the canvas will be displayed using the font size provided here.
  • baseFontColor="HexColorCode" : This attribute sets the base font color of the graph i.e., all the values and the names in the graph which lie on the canvas will be displayed using the font color provided here.
  • outCnvBaseFont = "FontName" : This attribute sets the base font family of the graph font which lies outside the canvas i.e., all the values and the names in the graph which lie outside the canvas will be displayed using the font name provided here.
  • outCnvBaseFontSize="FontSize" : This attribute sets the base font size of the graph i.e., all the values and the names in the graph which lie outside the canvas will be displayed using the font size provided here.
  • outCnvBaseFontColor="HexColorCode": This attribute sets the base font color of the graph i.e., all the values and the names in the graph which lie outside the canvas will be displayed using the font color provided here.

Candle Properties

  • candleWidth="NumericalValue" (Optional): If you explicitly wish to define the width of each candle in the chart, you can use this attribute. However, this attribute is optional in the sense that FusionCharts would automatically calculate the best fit value for the candle width.
  • bearBorderColor="HexColor": Border Color for a bear candle.
  • bearFillColor="HexColor": Fill Color for a bear candle.
  • bullBorderColor="HexColor": Border Color for a bull candle.
  • bullFillColor="HexColor": Fill Color for a bull candle. attributes and elements Attributes and child-elements of the elements help you create the x-axis labels on the chart. They also help you create the vertical category lines on the chart and configure their visual properties.

The element has the following attributes:

  • font='FontName' : This attribute helps you set the font face for the x-axis labels in specific.
  • fontSize='FontSize' : This attribute helps you set the font size for the x-axis labels in specific.
  • fontColor='HexColor' : This attribute helps you set the font color for the x-axis labels in specific.
  • verticalLineColor='HexColor' : This attribute helps you set the color of the category line (i.e., the vertical line drawn through the entire span of the canvas just above the category name)
  • verticalLineThickness='NumericalValue' : This attribute helps you set the thickness of the category line in pixels.
  • verticalLineAlpha='NumericalValue0-100' : This attribute helps you set the alpha (transparency) of the category line

For each category name, you'll need to define a element as under:

The element can have the following attributes:

  • name='String': x-axis label to be displayed.
  • xIndex='NumericalValue': x-axis position where the category name is to be displayed. In the candlestick chart, the x-axis is also numbered - i.e., it has an upper limit and a lower limit. For example, when you're plotting a chart to show the data for a month, the lower limit of x-axis would be 1 and the upper limit 31. So, when you need to render a category label for the 15th day of the month say "Mid-month", you'll have specify xIndex as 15 for that .
  • showLine='1/0' : Option to whether show or hide the line just above this particular category name. child elements The actual data of the chart comes under the element. For each data item, you've to specify a element as under:

The element can have the following attributes:

  • open="NumericalValue" : This attribute determines the open value for the data set. It is compulsory to provide this value.
  • high="NumericalValue" : This attribute determines the high value for the data set. It is compulsory to provide this value.
  • low ="NumericalValue" : This attribute determines the low value for the data set. It is compulsory to provide this value.
  • close ="NumericalValue" : This attribute determines the close value for the data set. It is compulsory to provide this value.
  • borderColor="HexColorCode" [Optional]: This attribute lets you change the border color of particular candle on the chart. All the candles on the chart follow the color code as specified in bearBorderColor and bullBorderColor attributes of the element. However, if in some case you want to highlight one particular candle by changing it's color, you can use this option.
  • color="HexColorCode" [Optional]: Similar to the border color (previous attribute), this attribute lets you set the fill color of a particular candle selectively.
  • xIndex="NumericalValue" [Optional]: x-axis position of the candle. In the candlestick chart, the x-axis is also numbered - i.e., it has an upper limit and a lower limit. For example, when you're plotting a chart to show the data for a month, the lower limit of x-axis would be 1 and the upper limit 31. So, when you're providing data for 15th day, you need to mention xIndex as 15. However, if you do not provide x-index for any of the elements, FusionCharts will auto number them for you starting from 1.
  • link="link" [Optional]: Sets the link for a particular candle Using the element (and child elements), you can define trend lines on the charts. Trend lines are the horizontal lines spanning the chart canvas that aid in interpretation of data with respect to some previous pre-determined figure. For each trend line on the chart, you need to define a element as under:

The element can have the following attributes:

  • startValue='NumericalValue': The starting y-axis value for the trendline. Say, if you want to plot a slanted trendline from value 102 to 109, the startValue would 102.
  • endValue='NumericalValue': The ending y-axis value for the trendline. Say, if you want to plot a slanted trendline from value 102 to 109, the endValue would 109. If you do not specify a value for endValue, it would automatically assume the same value as startValue.
  • color='HexCode' : Color of the trend line and its associated text.
  • displayValue='StringValue' : If you want to display a string caption for the trend line by its side, you can use this attribute. Example: displayValue='Last Month High'. When you don't supply this attribute, it automatically takes the value of startValue.
  • thickness='NumericalValue' : Thickness of the trend line
  • isTrendZone='1/0': Whether the trend would display a line, or a zone (filled colored rectangle).
  • showOnTop='1/0': Whether the trend line/zone would be displayed over the candles or under the candles.
  • alpha='NumericalValue0-100': Alpha (transparency) of the trend line In the next section we'll see a few examples of XML document for the candlestick chart.

Lucene学习总结之一:全文检索的基本原理

Posted on

Lucene学习总结之一:全文检索的基本原理

一、总论

根据http://lucene.apache.org/java/docs/index.html定义:

Lucene**是一个高效的,基于Java**的全文检索库。

所以在了解Lucene之前要费一番工夫了解一下全文检索。

那么什么叫做全文检索呢?这要从我们生活中的数据说起。

我们生活中的数据总体分为两种:结构化数据非结构化数据

  • 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。
  • 非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等。

当然有的地方还会提到第三种,半结构化数据,如XML,HTML等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。

非结构化数据又一种叫法叫全文数据。


按照数据的分类,搜索也分为两种:

  • 对结构化数据的搜索:如对数据库的搜索,用SQL语句。再如对元数据的搜索,如利用windows搜索对文件名,类型,修改时间进行搜索等。
  • 对非结构化数据的搜索:如利用windows的搜索也可以搜索文件内容,Linux下的grep命令,再如用Google和百度可以搜索大量内容数据。

对非结构化数据也即对全文数据的搜索主要有两种方法:

一种是顺序扫描法**(Serial Scanning):**所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。如果你有一个80G硬盘,如果想在上面找到一个内容包含某字符串的文件,不花他几个小时,怕是做不到。Linux下的grep命令也是这一种方式。大家可能觉得这种方法比较原始,但对于小数据量的文件,这种方法还是最直接,最方便的。但是对于大量的文件,这种方法就很慢了。

有人可能会说,对非结构化数据顺序扫描很慢,对结构化数据的搜索却相对较快(由于结构化数据有一定的结构可以采取一定的搜索算法加快速度),那么把我们的非结构化数据想办法弄得有一定结构不就行了吗?

这种想法很天然,却构成了全文检索的基本思路,也即将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。

这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引

这种说法比较抽象,举几个例子就很容易明白,比如字典,字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释。


这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)**。**


下面这幅图来自《Lucene in action》,但却不仅仅描述了Lucene的检索过程,而是描述了全文检索的一般过程。

image

全文检索大体分两个过程,索引创建**(Indexing)搜索索引**(Search)

  • 索引创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程。
  • 搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。

于是全文检索就存在三个重要问题:

1.**索引里面究竟存些什么?(Index)**

2.**如何创建索引?(Indexing)**

3.**如何对索引进行搜索?(Search)**

下面我们顺序对每个个问题进行研究。

二、索引里面究竟存些什么

索引里面究竟需要存些什么呢?

首先我们来看为什么顺序扫描的速度慢:

其实是由于我们想要搜索的信息和非结构化数据中所存储的信息不一致造成的。

非结构化数据中所存储的信息是每个文件包含哪些字符串,也即已知文件,欲求字符串相对容易,也即是从文件到字符串的映射。而我们想搜索的信息是哪些文件包含此字符串,也即已知字符串,欲求文件,也即从字符串到文件的映射。两者恰恰相反。于是如果索引总能够保存从字符串到文件的映射,则会大大提高搜索速度。

由于从字符串到文件的映射是文件到字符串映射的反向过程,于是保存这种信息的索引称为反向索引

反向索引的所保存的信息一般如下:

假设我的文档集合里面有100篇文档,为了方便表示,我们为文档编号从1到100,得到下面的结构

inverted index

左边保存的是一系列字符串,称为词典

每个字符串都指向包含此字符串的文档(Document)链表,此文档链表称为倒排表(Posting List)。

有了索引,便使保存的信息和要搜索的信息一致,可以大大加快搜索的速度。

比如说,我们要寻找既包含字符串“lucene”又包含字符串“solr”的文档,我们只需要以下几步:

  1. 取出包含字符串“lucene”的文档链表。

  2. 取出包含字符串“solr”的文档链表。

  3. 通过合并链表,找出既包含“lucene”又包含“solr”的文件。

inverted index merge

看到这个地方,有人可能会说,全文检索的确加快了搜索的速度,但是多了索引的过程,两者加起来不一定比顺序扫描快多少。的确,加上索引的过程,全文检索不一定比顺序扫描快,尤其是在数据量小的时候更是如此。而对一个很大量的数据创建索引也是一个很慢的过程。

然而两者还是有区别的,顺序扫描是每次都要扫描,而创建索引的过程仅仅需要一次,以后便是一劳永逸的了,每次搜索,创建索引的过程不必经过,仅仅搜索创建好的索引就可以了。

这也是全文搜索相对于顺序扫描的优势之一:一次索引,多次使用。

三、如何创建索引

全文检索的索引创建过程一般有以下几步:

第一步:一些要索引的原文档(Document)。

为了方便说明索引创建过程,这里特意用两个文件为例:

文件一:Students should be allowed to go out with their friends, but not allowed to drink beer.

文件二:My friend Jerry went to school to see his students but found them drunk which is not allowed.

第二步:将原文档传给分次组件(Tokenizer)。

分词组件(Tokenizer)会做以下几件事情(**此过程称为Tokenize)**:

1.**将文档分成一个一个单独的单词。**

2.**去除标点符号。**

3.**去除停词(Stop word)**。

所谓停词(Stop word)就是一种语言中最普通的一些单词,由于没有特别的意义,因而大多数情况下不能成为搜索的关键词,因而创建索引时,这种词会被去掉而减少索引的大小。

英语中挺词(Stop word)如:“the”,“a”,“this”等。

对于每一种语言的分词组件(Tokenizer),都有一个停词(stop word)集合。


经过分词(Tokenizer)**后得到的结果称为词元(Token)**。

在我们的例子中,便得到以下词元(Token):

“Students”,“allowed”,“go”,“their”,“friends”,“allowed”,“drink”,“beer”,“My”,“friend”,“Jerry”,“went”,“school”,“see”,“his”,“students”,“found”,“them”,“drunk”,“allowed”。

第三步:将得到的词元(Token)传给语言处理组件(Linguistic Processor)。

语言处理组件(linguistic processor)主要是对得到的词元(Token)做一些同语言相关的处理。

对于英语,语言处理组件(Linguistic Processor)**一般做以下几点:**

1.**变为小写(Lowercase)**。

2.**将单词缩减为词根形式,如“cars”到“car”等。这种操作称为:stemming**。

3.**将单词转变为词根形式,如“drove”到“drive”等。这种操作称为:lemmatization**。

Stemming 和 lemmatization的异同:

  • 相同之处:Stemming和lemmatization都要使词汇成为词根形式。
  • 两者的方式不同:

  • Stemming采用的是“缩减”的方式:“cars”到“car”,“driving”到“drive”。

  • Lemmatization采用的是“转变”的方式:“drove”到“drove”,“driving”到“drive”。
  • 两者的算法不同:

  • Stemming主要是采取某种固定的算法来做这种缩减,如去除“s”,去除“ing”加“e”,将“ational”变为“ate”,将“tional”变为“tion”。

  • Lemmatization主要是采用保存某种字典的方式做这种转变。比如字典中有“driving”到“drive”,“drove”到“drive”,“am, is, are”到“be”的映射,做转变时,只要查字典就可以了。
  • Stemming和lemmatization不是互斥关系,是有交集的,有的词利用这两种方式都能达到相同的转换。

语言处理组件(linguistic processor)的结果称为词(Term)**。**

在我们的例子中,经过语言处理,得到的词(Term)如下:

“student”,“allow”,“go”,“their”,“friend”,“allow”,“drink”,“beer”,“my”,“friend”,“jerry”,“go”,“school”,“see”,“his”,“student”,“find”,“them”,“drink”,“allow”。

也正是因为有语言处理的步骤,才能使搜索drove,而drive也能被搜索出来。

第四步:将得到的词(Term)传给索引组件(Indexer)。

索引**组件(Indexer)主要做以下几件事情:**

1. 利用得到的词(Term)创建一个字典。

在我们的例子中字典如下: Term Document ID student 1 allow 1 go 1 their 1 friend 1 allow 1 drink 1 beer 1 my 2 friend 2 jerry 2 go 2 school 2 see 2 his 2 student 2 find 2 them 2 drink 2 allow 2

2.**对字典按字母顺序进行排序。**

Term Document ID allow 1 allow 1 allow 2 beer 1 drink 1 drink 2 find 2 friend 1 friend 2 go 1 go 2 his 2 jerry 2 my 2 school 2 see 2 student 1 student 2 their 1 them 2


3.**合并相同的词(Term)成为文档倒排(Posting List)链表。**

postinglist

在此表中,有几个定义:

  • Document Frequency 即文档频次,表示总共有多少文件包含此词(Term)。
  • Frequency 即词频率,表示此文件中包含了几个此词(Term)。

所以对词(Term) “allow”来讲,总共有两篇文档包含此词(Term),从而词(Term)后面的文档链表总共有两项,第一项表示包含“allow”的第一篇文档,即1号文档,此文档中,“allow”出现了2次,第二项表示包含“allow”的第二个文档,是2号文档,此文档中,“allow”出现了1次。

到此为止,索引已经创建好了,我们可以通过它很快的找到我们想要的文档。

而且在此过程中,我们惊喜地发现,搜索“drive”,“driving”,“drove”,“driven”也能够被搜到。因为在我们的索引中,“driving”,“drove”,“driven”都会经过语言处理而变成“drive”,在搜索时,如果您输入“driving”,输入的查询语句同样经过我们这里的一到三步,从而变为查询“drive”,从而可以搜索到想要的文档。

三、如何对索引进行搜索?

到这里似乎我们可以宣布“我们找到想要的文档了”。

然而事情并没有结束,找到了仅仅是全文检索的一个方面。不是吗?如果仅仅只有一个或十个文档包含我们查询的字符串,我们的确找到了。然而如果结果有一千个,甚至成千上万个呢?那个又是您最想要的文件呢?

打开Google吧,比如说您想在微软找份工作,于是您输入“Microsoft job”,您却发现总共有22600000个结果返回。好大的数字呀,突然发现找不到是一个问题,找到的太多也是一个问题。在如此多的结果中,如何将最相关的放在最前面呢?

![clip_image002[4]](http://images.cnblogs.com/cnblogs_com/forfuture1978/WindowsLiveWriter/185c4e9316f3_147FA/clip_image0024.jpg)

当然Google做的很不错,您一下就找到了jobs at Microsoft。想象一下,如果前几个全部是“Microsoft does a good job at software industry…”将是多么可怕的事情呀。

如何像Google一样,在成千上万的搜索结果中,找到和查询语句最相关的呢?

如何判断搜索出的文档和查询语句的相关性呢?

这要回到我们第三个问题:如何对索引进行搜索?

搜索主要分为以下几步:

第一步:用户输入查询语句。

查询语句同我们普通的语言一样,也是有一定语法的。

不同的查询语句有不同的语法,如SQL语句就有一定的语法。

查询语句的语法根据全文检索系统的实现而不同。最基本的有比如:AND, OR, NOT等。

举个例子,用户输入语句:lucene AND learned NOT hadoop。

说明用户想找一个包含lucene和learned然而不包括hadoop的文档。

第二步:对查询语句进行词法分析,语法分析,及语言处理。

由于查询语句有语法,因而也要进行语法分析,语法分析及语言处理。

1. 词法分析主要用来识别单词和关键字。

如上述例子中,经过词法分析,得到单词有lucene,learned,hadoop, 关键字有AND, NOT。

如果在词法分析中发现不合法的关键字,则会出现错误。如lucene AMD learned,其中由于AND拼错,导致AMD作为一个普通的单词参与查询。

2. 语法分析主要是根据查询语句的语法规则来形成一棵语法树。

如果发现查询语句不满足语法规则,则会报错。如lucene NOT AND learned,则会出错。

如上述例子,lucene AND learned NOT hadoop形成的语法树如下:

语法树

3. 语言处理同索引过程中的语言处理几乎相同。

如learned变成learn等。

经过第二步,我们得到一棵经过语言处理的语法树。

语法树1

第三步:搜索索引,得到符合语法树的文档。

此步骤有分几小步:

  1. 首先,在反向索引表中,分别找出包含lucene,learn,hadoop的文档链表。**
  2. 其次,对包含lucene,learn的链表进行合并操作,得到既包含lucene又包含learn的文档链表。**
  3. 然后,将此链表与hadoop的文档链表进行差操作,去除包含hadoop的文档,从而得到既包含lucene又包含learn而且不包含hadoop的文档链表。**
  4. 此文档链表就是我们要找的文档。

第四步:根据得到的文档和查询语句的相关性,对结果进行排序。

虽然在上一步,我们得到了想要的文档,然而对于查询结果应该按照与查询语句的相关性进行排序,越相关者越靠前。

如何计算文档和查询语句的相关性呢?

不如我们把查询语句看作一片短小的文档,对文档与文档之间的相关性(relevance)进行打分(scoring),分数高的相关性好,就应该排在前面。

那么又怎么对文档之间的关系进行打分呢?

这可不是一件容易的事情,首先我们看一看判断人之间的关系吧。

首先看一个人,往往有很多要素,如性格,信仰,爱好,衣着,高矮,胖瘦等等。

其次对于人与人之间的关系,不同的要素重要性不同,性格,信仰,爱好可能重要些,衣着,高矮,胖瘦可能就不那么重要了,所以具有相同或相似性格,信仰,爱好的人比较容易成为好的朋友,然而衣着,高矮,胖瘦不同的人,也可以成为好的朋友。

因而判断人与人之间的关系,首先要找出哪些要素对人与人之间的关系最重要,比如性格,信仰,爱好。其次要判断两个人的这些要素之间的关系,比如一个人性格开朗,另一个人性格外向,一个人信仰佛教,另一个信仰上帝,一个人爱好打篮球,另一个爱好踢足球。我们发现,两个人在性格方面都很积极,信仰方面都很善良,爱好方面都爱运动,因而两个人关系应该会很好。

我们再来看看公司之间的关系吧。

首先看一个公司,有很多人组成,如总经理,经理,首席技术官,普通员工,保安,门卫等。

其次对于公司与公司之间的关系,不同的人重要性不同,总经理,经理,首席技术官可能更重要一些,普通员工,保安,门卫可能较不重要一点。所以如果两个公司总经理,经理,首席技术官之间关系比较好,两个公司容易有比较好的关系。然而一位普通员工就算与另一家公司的一位普通员工有血海深仇,怕也难影响两个公司之间的关系。

因而判断公司与公司之间的关系,首先要找出哪些人对公司与公司之间的关系最重要,比如总经理,经理,首席技术官。其次要判断这些人之间的关系,不如两家公司的总经理曾经是同学,经理是老乡,首席技术官曾是创业伙伴。我们发现,两家公司无论总经理,经理,首席技术官,关系都很好,因而两家公司关系应该会很好。

分析了两种关系,下面看一下如何判断文档之间的关系了。

首先,一个文档有很多词(Term)组成,如search, lucene, full-text, this, a, what等。

其次对于文档之间的关系,不同的Term重要性不同,比如对于本篇文档,search, Lucene, full-text就相对重要一些,this, a , what可能相对不重要一些。所以如果两篇文档都包含search, Lucene,fulltext,这两篇文档的相关性好一些,然而就算一篇文档包含this, a, what,另一篇文档不包含this, a, what,也不能影响两篇文档的相关性。

因而判断文档之间的关系,首先找出哪些词(Term)对文档之间的关系最重要,如search, Lucene, fulltext。然后判断这些词(Term)之间的关系。

找出词(Term)**对文档的重要性的过程称为计算词的权重(Term weight)**的过程。

计算词的权重(term weight)有两个参数,第一个是词(Term),第二个是文档(Document)。

词的权重(Term weight)表示此词(Term)在此文档中的重要程度,越重要的词(Term)有越大的权重(Term weight),因而在计算文档之间的相关性中将发挥更大的作用。

判断词(Term)**之间的关系从而得到文档相关性的过程应用一种叫做向量空间模型的算法(Vector Space Model)**。


下面仔细分析一下这两个过程:

1. 计算权重(Term weight)的过程。

影响一个词(Term)在一篇文档中的重要性主要有两个因素:

  • Term Frequency (tf):即此Term在此文档中出现了多少次。tf 越大说明越重要。
  • Document Frequency (df):即有多少文档包含次Term。df 越大说明越不重要。

容易理解吗?词(Term)在文档中出现的次数越多,说明此词(Term)对该文档越重要,如“搜索”这个词,在本文档中出现的次数很多,说明本文档主要就是讲这方面的事的。然而在一篇英语文档中,this出现的次数更多,就说明越重要吗?不是的,这是由第二个因素进行调整,第二个因素说明,有越多的文档包含此词(Term), 说明此词(Term)太普通,不足以区分这些文档,因而重要性越低。

这也如我们程序员所学的技术,对于程序员本身来说,这项技术掌握越深越好(掌握越深说明花时间看的越多,tf越大),找工作时越有竞争力。然而对于所有程序员来说,这项技术懂得的人越少越好(懂得的人少df小),找工作越有竞争力。人的价值在于不可替代性就是这个道理。

道理明白了,我们来看看公式:

image

image

这仅仅只term weight计算公式的简单典型实现。实现全文检索系统的人会有自己的实现,Lucene就与此稍有不同。

2. 判断Term之间的关系从而得到文档相关性的过程,也即向量空间模型的算法(VSM)。

我们把文档看作一系列词(Term),每一个词(Term)都有一个权重(Term weight),不同的词(Term)根据自己在文档中的权重来影响文档相关性的打分计算。

于是我们把所有此文档中词(term)的权重(term weight) 看作一个向量。

Document = {term1, term2, …… ,term N}

Document Vector = {weight1, weight2, …… ,weight N}

同样我们把查询语句看作一个简单的文档,也用向量来表示。

Query = {term1, term 2, …… , term N}

Query Vector = {weight1, weight2, …… , weight N}

我们把所有搜索出的文档向量及查询向量放到一个N维空间中,每个词(term)是一维。

如图:

vsm

我们认为两个向量之间的夹角越小,相关性越大。

所以我们计算夹角的余弦值作为相关性的打分,夹角越小,余弦值越大,打分越高,相关性越大。

有人可能会问,查询语句一般是很短的,包含的词(Term)是很少的,因而查询向量的维数很小,而文档很长,包含词(Term)很多,文档向量维数很大。你的图中两者维数怎么都是N呢?

在这里,既然要放到相同的向量空间,自然维数是相同的,不同时,取二者的并集,如果不含某个词(Term)时,则权重(Term Weight)为0。

相关性打分公式如下:

image

举个例子,查询语句有11个Term,共有三篇文档搜索出来。其中各自的权重(Term weight),如下表格。 t1

t2

t3

t4

t5

t6

t7

t8

t9

t10

t11 D1

0

0

.477

0

.477

.176

0

0

0

.176

0 D2

0

.176

0

.477

0

0

0

0

.954

0

.176 D3

0

.176

0

0

0

.176

0

0

0

.176

.176 Q

0

0

0

0

0

.176

0

0

.477

0

.176

于是计算,三篇文档同查询语句的相关性打分分别为:

image

image

image

于是文档二相关性最高,先返回,其次是文档一,最后是文档三。

到此为止,我们可以找到我们最想要的文档了。

说了这么多,其实还没有进入到Lucene,而仅仅是信息检索技术(Information retrieval)中的基本理论,然而当我们看过Lucene后我们会发现,Lucene是对这种基本理论的一种基本的的实践。所以在以后分析Lucene的文章中,会常常看到以上理论在Lucene中的应用。

在进入Lucene之前,对上述索引创建和搜索过程所一个总结,如图:

此图参照http://www.lucene.com.cn/about.htm中文章《开放源代码的全文检索引擎Lucene》

clip_image016

1. 索引过程:

1)**有一系列被索引文件**

2)**被索引文件经过语法分析和语言处理形成一系列词(Term)**。

3)**经过索引创建形成词典和反向索引表。**

4)**通过索引存储将索引写入硬盘。**

2. 搜索过程:

a)**用户输入查询语句。**

b)**对查询语句经过语法分析和语言分析得到一系列词(Term)**。

c)**通过语法分析得到一个查询树。**

d)**通过索引存储将索引读入到内存。**

e)**利用查询树搜索索引,从而得到每个词(Term)**的文档链表,对文档链表进行交,差,并得到结果文档。

f)**将搜索到的结果文档对查询的相关性进行排序。**

g)**返回查询结果给用户。**

下面我们可以进入Lucene的世界了。

另:

CSDN中此文章链接为http://blog.csdn.net/forfuture1978/archive/2009/10/22/4711308.aspx

Javaeye中此文章链接为http://forfuture1978.javaeye.com/blog/546771

评论

/#1楼2010-02-23 08:36Framework

有深度

支持(0)反对(0) http://pic.cnitblog.com/face/u102545.png /#2楼2010-07-19 14:43a-peng

谢谢楼主这么好的文章,有两个地方有点不明白。

  1. 计算权重的公式 w = tf / log(n / df) log没有底数不知道要怎么计算 比如 n = 8 即8个文档 df = 2 即包含该词的文档有2个 tf = 5 即该词在该文档中出现5次 w = 5 / log4 log没有底数,结果出不来。
  2. 举个例子,查询语句有11个Term,共有三篇文档搜索出来。其中各自的权重(Term weight),如下表格。 表格中最后一行,查询语句中词的权重不知是如何计算出来的,是D1+D2+D3吗,不像,为什么像D2,D3中都是176而Q中确是0呢?

支持(0)反对(0) /#3楼2010-07-19 15:12a-peng

t2与t11 的数据是一样的都是0, 176, 176可是Q在t2与t11的结果确完全不一样,很困惑。

支持(0)反对(0) /#4楼2011-10-12 16:51林伟健

Q的权重怎么来?

支持(0)反对(0) /#5楼[楼主] 2011-10-12 22:33觉先

引用a-peng: t2与t11 的数据是一样的都是0, 176, 176可是Q在t2与t11的结果确完全不一样,很困惑。 不好意思,可能是笔误了。不是查询语句中有11个Term,而是整个向量空间有11个Term。 为0的可以认为此D或者Q不包含此Term。 在这个例子中,Query包含三个Term (t6, t9, t11), D1 (t3, t5, t6, t10), D2 (t2, t4, t9, t11) D3 (t2, t6, t10, t11) log的底数可以不同的系统根据自己想选取的平滑程度选取。 在这个例子中,底数是10. n = 3 如果tf = 1(此文章中此Term出现了1次), df=2(两篇文章包含此Term), 则1 / log(3/2) = 0.176 如果tf = 1, df = 1, 则 1 / log3 = 0.477 如果tf = 2, df = 1, 则 2 /* log3 = 0.954

支持(1)反对(0) http://pic.cnitblog.com/face/u103165.jpg /#6楼2012-02-16 10:49珍帅久久

很有深度,但又通俗易懂,不可多得的好文章啊。

支持(0)反对(0) /#7楼2012-03-06 21:32waceunmn

不错的内容啊

支持(0)反对(0) /#8楼2012-05-18 22:52scncpb

谢谢,讲的真详细,把具体的过程讲的极其清楚。。

支持(0)反对(0) /#9楼2012-06-29 17:32潘奕涛

很好很强大

支持(0)反对(0) http://pic.cnitblog.com/face/u16379.jpg /#10楼2012-09-11 13:50久依

内容非常详细,就是我的数据不怎么好嘿嘿!

支持(0)反对(0) /#11楼2012-09-11 22:16心有多大,舞台就有多大

非常好,草率的看完了

支持(0)反对(0) /#12楼2012-11-30 16:53流民无产者

非常好的文章,谢谢博主的分享。 刚开始也没看懂Query的weight如何计算的,后来看了回复就明白了。 只是还有一点不明白的地方,希望博主解答。 tf和df的计算:tf表示的term在一个doc里的权重值。但是df对于一次查询是个常量值,不知道计算有何意义。我觉得df的值对于查询的doc排序没有影响。

支持(0)反对(0) /#13楼2012-12-13 18:29coodoing

很详细 受用

支持(0)反对(0) http://pic.cnitblog.com/face/u74734.png?id=23111117 /#14楼2013-01-29 20:04星情

总结得很全面且有深度

支持(0)反对(0) http://pic.cnitblog.com/face/u70745.jpg?id=22103524 /#15楼2013-04-14 21:02IoT小菜

@a-peng 计算机里面权重默认是2

支持(0)反对(0) http://pic.cnitblog.com/face/456333/20130617210829.png /#16楼26660682013/4/25 11:27:402013-04-25 11:27Echofool

这么好的文章,为什么没人评论呢?感谢楼主分享。受用了

支持(0)反对(0) 来源: <Lucene学习总结之一:全文检索的基本原理 - 觉先 - 博客园>