1,首先测试在本机上开启三个tomcat的服务器:一个端口是80,另一个是9888
2,按照标题一的配置对第二和第三个tomcat服务器进行类似的配置,注意SolrHome的目录不要相同即可,其他的配置不变. 例如:以本机为例
tomcat命名 |
URL |
SolrHome目录URI |
web.xml配置 |
tomcat0 (master) |
http://localhost:80/solr |
D:\WORK\SolrHome\solr |
<env-entry-value>D:\WORK\SolrHome\solr</env-entry-value> |
tomcat1 (slave) |
http://localhost:9888/solr |
E:\WORK\SolrHome\solr |
<env-entry-value>E:\WORK\SolrHome\solr</env-entry-value> |
tomcat2 (salve) |
http://localhost:9008/solr |
F:\WORK\SolrHome\solr |
<env-entry-value>F:\WORK\SolrHome\solr</env-entry-value> |
3,以上两步配置好之后,在主服务器tomcat0(master)的SolrHome中找到solrconfig.xml文件,加入如下配置.
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="master">
<str name="replicateAfter">commit</str>
<str name="replicateAfter">startup</str>
<str name="confFiles">schema.xml,stopwords.txt</str>
</lst>
</requestHandler>
在从服务器tomcat1(slave)和tomcat1(slave)的SolrHome中找到solrconfig.xml文件加入如下配置:
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="slave">
<str name="masterUrl">http://localhost/solr/replication</str>
<str name="pollInterval">00:00:60</str>
</lst>
</requestHandler>
4,在tomcat0上创建索引,使用客户端solrj创建索引,jar包在apache-solr-1.4.1压缩包中.代码如下:
public class SlorTest3 {
private static CommonsHttpSolrServer server = null;
// private static SolrServer server = null;
public SlorTest3(){
try {
server = new CommonsHttpSolrServer("http://localhost/solr");
server.setConnectionTimeout(100);
server.setDefaultMaxConnectionsPerHost(100);
server.setMaxTotalConnections(100);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testIndexCreate(){
List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
for(int i=300;i<500;i++){
SolrInputDocument doc = new SolrInputDocument();
doc.addField("zjid", i); //需要在sechma.xml中配置字段
doc.addField("title", "云状空化多个气泡的生长和溃灭");
doc.addField("ssid", "ss"+i);
doc.addField("dxid", "dx"+i);
docs.add(doc);
}
try {
server.add(docs);
server.commit();
System.out.println("----索引创建完毕!!!----");
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5,分别启动三台tomcat服务器.打开IE浏览器分别输入:其中localhost=192.168.169.121
http://localhost:9888/solr 点击即可从主solr服务器上复制索引
三、Solr服务器分发(shard)配置
1, 开启四台tomcat服务器,其中三台在本机上,一台在远端.清单如下:
注意:四台服务器的配置要相同.其中的schema.xml字段配置一定要一致.
Name |
URL |
SolrHome目录URI |
|
tomcatQuery |
http://localhost:80/solr |
D:\WORK\SolrHome\solr |
|
tomcat0 (shard) |
http://localhost:9888/solr |
E:\WORK\SolrHome\solr |
|
tomcat1 (shard) |
http://localhost:9008/solr |
F:\WORK\SolrHome\solr |
|
tomcat2 (shard) |
http://192.168.169.48:9888/solr |
D:\WORK\SolrHome\solr |
|
2, 配置较简单,只需要在tomcatQuery上的SoleHome的solrconfig.xml文件中修改
其他的solr服务器不需要配置。
<requestHandler name="standard" class="solr.SearchHandler" default="true">
<!-- default values for query parameters -->
<lst name="defaults">
<str name="echoParams">explicit</str>
<str name="shards">localhost:9088/solr,localhost:9888/solr,192.168.169.48:9888/solr</str>
<!--
<int name="rows">10</int>
<str name="fl">*</str>
<str name="version">2.1</str>
-->
</lst>
</requestHandler>
3, 使用slorj的清除原有的索引.或者手动删除。
4, 编写代码,将lucene建立的索引(1G左右,874400条记录),按照比例通过solrj分发到三台solr(shard)服务器上,代码如下:
public class IndexCreate{
private static CommonsHttpSolrServer server;
public CommonsHttpSolrServer getServer(String hostUrl){
CommonsHttpSolrServer server = null;
try {
server = new CommonsHttpSolrServer(hostUrl);
server.setConnectionTimeout(100);
server.setDefaultMaxConnectionsPerHost(100);
server.setMaxTotalConnections(100);
} catch (IOException e) {
System.out.println("请检查tomcat服务器或端口是否开启!");
}
return server;
}
@SuppressWarnings("deprecation")
public void readerHostCreate(String[] hosts) throwsCorruptIndexException, IOException{
IndexReader reader = IndexReader.open("c:\\index");
System.out.println("总记录数: "+reader.numDocs());
int hostNum = hosts.length;
int lengh = reader.numDocs()/hostNum; //根据主机数平分索引长度
int j = reader.numDocs()%hostNum; //取余
for(int i = 0;i<hosts.length;i++){
long startTime = new Date().getTime();
String url = hosts[i].substring(hosts[i].indexOf("//")+2,hosts[i].lastIndexOf("/"));
System.out.println("第"+(i+1)+"次,在主机:"+url+" 上创建索引,创建时间"+new Date());
if(i==(hosts.length-1)){
hostlist(reader,lengh*i,lengh*(i+1)+j,hosts[i]);
}else{
hostlist(reader,lengh*i,lengh*(i+1),hosts[i]);
}
System.out.println("结束时间"+new Date());
long endTime = new Date().getTime();
long ms = (endTime-startTime)%60000-(((endTime-startTime)%60000)/1000)*1000;
System.out.println("本次索引创建完毕,一共用了"+(endTime-startTime)/60000+"分" +
""+((endTime-startTime)%60000)/1000+"秒"+ms+"毫秒");
System.out.println("****************************");
}
reader.close();
}
@SuppressWarnings("static-access")
public void hostlist(IndexReader reader,int startLengh,intendLengh,String hostUrl) throws CorruptIndexException, IOException{
List<BookIndex> beans = new LinkedList<BookIndex>();
int count = 0;
this.server = getServer(hostUrl);
for(int i=startLengh;i<endLengh;i++){
Document doc = reader.document(i);
BookIndex book = new BookIndex();
book.setZjid(doc.getField("zjid").stringValue());
book.setTitle(doc.getField("title").stringValue());
book.setSsid(doc.getField("ssid").stringValue());
book.setDxid(doc.getField("dxid").stringValue());
book.setBookname(doc.getField("bookname").stringValue());
book.setAuthor(doc.getField("author").stringValue());
book.setPublisher(doc.getField("publisher").stringValue());
book.setPubdate(doc.getField("pubdate").stringValue());
book.setYear(doc.getField("year").stringValue());
book.setFenlei(doc.getField("fenlei").stringValue());
book.setscore1(doc.getField("score").stringValue());
book.setIsbn(doc.getField("isbn").stringValue());
book.setFenleiurl(doc.getField("fenleiurl").stringValue());
book.setMulu(doc.getField("mulu").stringValue());
book.setIsp(doc.getField("isp").stringValue());
book.setIep(doc.getField("iep").stringValue());
beans.add(book);
if(beans.size()%3000==0){
createIndex(beans,hostUrl,server);
beans.clear();
System.out.println("---索引次数:"+(count+1)+"---");
count++;
}
}
System.out.println("beansSize 的大小 "+beans.size());
if(beans.size()>0){
createIndex(beans,hostUrl,server);
beans.clear();
}
}
public void createIndex(List<BookIndex> beans,String hostUrl,CommonsHttpSolrServer server){
try {
server.addBeans(beans);
server.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws CorruptIndexException, IOException{
IndexCreate as = new IndexCreate();
String[] hosts = new String[] {"http://192.168.169.121:9888/solr","http://192.168.169.121:9088/solr","http://192.168.169.48:9888/solr"};
long startTime = new Date().getTime();
as.readerHostCreate(hosts);
long endTime = new Date().getTime();
System.out.println("-------------------");
long ms = (endTime-startTime)%60000-(((endTime-startTime)%60000)/1000)*1000;
System.out.println("全部索引创建完毕,一共用了"+(endTime-startTime)/60000+"分" +
""+((endTime-startTime)%60000)/1000+"秒"+ms+"毫秒");
}
}
JavaBean类BookIndex.java代码如下:
说明变量名与sechma.xml中的配置要相同.注意:不能使用score这个变量或者字段,与slor配置冲突,报exception。
import org.apache.solr.client.solrj.beans.Field;
public class BookIndex {
@Field
private String zjid ;
@Field
private String title;
@Field
private String ssid;
@Field
private String dxid;
@Field
private String bookname;
@Field
private String author;
@Field
private String publisher;
@Field
private String pubdate;
@Field
private String year;
@Field
private String fenlei;
@Field
private String score1;
@Field
private String isbn;
@Field
private String fenleiurl;
@Field
private String mulu;
@Field
private String isp;
@Field
private String iep;
public getters();//get方法
public setters();//set方法
}
5, 同时开启四台服务器,运行上面代码:
6, 打开IE查询
打开http://192.168.168.48:9888/solr
第一步,将apache-solr-1.4.1\example下的multicore复制到先前配置的solr/home下。
其中multicore下的solr.xml配置如下:
<solr persistent="false">
<cores adminPath="/admin/cores">
<core name="core0" instanceDir="core0">
<property name="dataDir" value="/data/core0" />
</core>
<core name="core1" instanceDir="core1">
<property name="dataDir" value="/data/core1" />
</core>
<core name="core2" instanceDir="core2">
<property name="dataDir" value="/data/core2" />
</core>
</cores>
</solr>
第二步,修改Tomcat 6.0\webapps\solr\WEB-INF下的web.xml文件如下
<env-entry-value>D:\WORK\SolrHome\multicore</env-entry-value>
第三步,开启服务器,打开IEhttp://localhost/solr
1,SolrJ的用法
solrJ是与solr服务器交互的客户端工具.使用solrJ不必考虑solr服务器的输出格式,以及对文档的解析。solrJ会根据用户发送的请求将数据结果集(collection)返回给用户.
2,使用SolrJ建立索引
事例代码:
//得到连接solr服务器的CommonsHttpSolrServer对象.通过这个对象处理用户提交的请求:
CommonsHttpSolrServer server = new CommonsHttpSolrServer("http://localhost:9888/solr");
public void testIndexCreate(){
List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
// SolrInputDocumentle类似与Document类,用于创建索引文档,和向文档中添加字段
for(int i=300;i<500;i++){
SolrInputDocument doc = new SolrInputDocument();
doc.addField("zjid", i+"_id");
doc.addField("title", i+"_title");
doc.addField("ssid", "ss_"+i);
doc.addField("dxid", "dx_"+i);
docs.add(doc);
}
try {
server.add(docs);
server.commit();//以更新(update)的方式提交
System.out.println("----索引创建完毕!!!----");
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
以javaBean的方式创建索引:
public class BookIndex {
@Field
private String zjid;
@Field
private String zhangjie;
@Field
private String ssid;
@Field
private String qwpos;
@Field
private String publishDate;
@Field
private String mulu;
@Field
private String fenleiurl;
@Field
private String fenlei;
@Field
private String dxid;
@Field
private String author;
@Field
private String address;
@Field
private String bookname;
…………………
}
public void testBean(){
List<BookIndex> beans = new ArrayList<BookIndex>();
for(int i=0;i<10;i++){
BookIndex book = new BookIndex();
book.setZjid(i+"id");
book.setTitle(i+"title");
//set方法
beans.add(book);
}
try {
server.addBeans(beans);
server.commit();
System.out.println("----索引创建完毕!!!----");
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
3, SolrJ常见的查询
a, 查询索引中的全部字段的内容: SolrQuery query = new SolrQuery("*:*");
事例代码:
public void testQuery1(){
SolrQuery query = new SolrQuery("*:*");
query.setStart(20);//设置起始位置
query.setRows(10); //查询组数
QueryResponse response = null;
try {
response = server.query(query);//响应向服务器提交的查询请求
System.out.println(response);
} catch (SolrServerException e) {
e.printStackTrace();
}
List<SolrDocument> docs = response.getResults();//得到结果集
for(SolrDocument doc:docs){//遍历结果集
for(Iterator iter = doc.iterator();iter.hasNext();){
Map.Entry<String, Object> entry = (Entry<String, Object>)iter.next();
System.out.print("Key :"+entry.getKey()+" ");
System.out.println("Value :"+entry.getValue());
}
System.out.println("------------");
}
}
b, 查询某一字段的内容
String queryString = “zjid:5_id”;//写法为字段名:查询的内容
SolrQuery query = new SolrQuery(queryString);
c, 查询copyField的内容
copyField是查询的默认字段,当不指明查询字段的field的时。查询的请求会在copyField匹配: 详细参见schema..xml的配置.
String queryString = “XXX”
SolrQuery query = new SolrQuery(queryString);
4, 索引删除
事例代码 :
public void testClear() {
server.setRequestWriter(new BinaryRequestWriter());//提高性能采用流输出方式
try {
server.deleteByQuery("*:*");
server.commit();
System.out.println("----清除索引---");
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
5, 高亮的使用Highlight
public List<Book> getQueryString(String queryString,int start,int pageSize) {
SolrQuery query = new SolrQuery(queryString);
query.setHighlight(true); //开启高亮组件
query.addHighlightField("mulu");//高亮字段
query.setHighlightSimplePre("<font color=\"red\">");//标记
query.setHighlightSimplePost("</font>");
query.set("hl.usePhraseHighlighter", true);
query.set("hl.highlightMultiTerm", true);
query.set("hl.snippets", 3);//三个片段,默认是1
query.set("hl.fragsize", 50);//每个片段50个字,默认是100
//
query.setStart(start); //起始位置 …分页
query.setRows(pageSize);//文档数
try {
response = server.query(query);
} catch (SolrServerException e) {
e.printStackTrace();
}
List<BookIndex> bookLists = response.getBeans(BookIndex.class);
Map<String,Map<String,List<String>>> h1 = response.getHighlighting();
List<Book> books = new ArrayList<Book>();
for(BookIndex bookIndex : bookLists){
Map<String,List<String>> map = h1.get(bookIndex.getZjid());
//以文档的唯一id作为Map<String,Map<String,List<String>>>的key值.
Book book = new Book();
//copy字段
book.setBookname(bookIndex.getBookname());
book.setZjid(bookIndex.getZjid());
if(map.get("mulu")!=null){
List<String> strMulu = map.get("mulu");
StringBuffer buf = new StringBuffer();
for(int i =0;i<strMulu.size();i++){
buf.append(strMulu.get(i));
buf.append("...");
if(i>3){
break;
}
}
book.setSummary(buf.toString());
}else{
if(bookIndex.getMulu().length()>100){
book.setSummary(bookIndex.getMulu().substring(0,100)+"...");
}else{
book.setSummary(bookIndex.getMulu()+"...");
}
}
books.add(book);
}
return books;
}
6, 分组Fact
//需要注意的是参与分组的字段是不需要分词的,比如:产品的类别.kind
public void testFact(){
String queryString = "kind:儿童图书";
SolrQuery query = new SolrQuery().setQuery(queryString);
query.setFacet(true); //开启分组
query.addFacetField("bookname");//分组字段
query.addFacetField("title");
query.setFacetMinCount(1);
query.addSortField( "zjid", SolrQuery.ORDER.asc );//排序字段
query.setRows(10);
QueryResponse response = null;
try {
response = server.query(query);
System.out.println(response);
} catch (SolrServerException e) {
e.printStackTrace();
}
List<FacetField> facets = response.getFacetFields();
for (FacetField facet : facets) {
System.out.println("Facet:" + facet);
}
}
首先说明的是索引来源,是根据已有的lucene索引上开发的,又因为lucene的索引直接用solrJ应用效果不好,会出现很多问题,找不到类似的解决办法,比如全字段查询,和高亮分组等,和多级索引目录…。但用solrJ创建的索引不存在类似的问题.
大致的思路是,读取已有的lucene索引 ,再用solrJ创建索引并分发到多台机器上,最后再做开发.
第一步:读取lucene的多级索引目录,用solrJ创建和分发索引;
需注意的是:要加大虚拟机的内存,因为采用的map做为缓存,理论上虚拟机的内存大,map的存储的索引文档数也就多.主要是针对内存溢出.
代码 :
package org.readerIndex;
import org.apache.solr.client.solrj.beans.Field;
public class BookIndex2 {
@Field
private String zjid;
@Field
private String zhangjie;
@Field
private String ssid;
@Field
private String qwpos;
@Field
private String publishDate;
@Field
private String mulu;
@Field
private String fenleiurl;
@Field
private String fenlei;
@Field
private String dxid;
@Field
private String author;
@Field
private String address;
@Field
private String bookname;
public String getZjid() {
return zjid;
…………………………………………
}
package org.readerIndex;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
public class ReaderIndex {
public CommonsHttpSolrServer getServer(String hostUrl){
CommonsHttpSolrServer server = null;
try {
server = new CommonsHttpSolrServer(hostUrl);
server.setConnectionTimeout(100);
server.setDefaultMaxConnectionsPerHost(100);
server.setMaxTotalConnections(100);
} catch (IOException e) {
System.out.println("请检查tomcat服务器或端口是否开启!");
}
return server;
}
public void indexDocuements(String path,String[] hostUrls) throwsCorruptIndexException, LockObtainFailedException, IOException{
File pareFile = new File(path);
List<String> list = new ArrayList<String>();
getFile(pareFile,list); //递归方法得到路径保存到list中
System.out.println("***程序一共递归到"+list.size()+"个索引目录***");
int arevageSize = list.size()/hostUrls.length;// 根据主机数平分目录
int remainSize = list.size()%hostUrls.length;//取余
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for(int i=0;i<hostUrls.length;i++){
Date startDate = new Date();
String url = hostUrls[i].substring(hostUrls[i].indexOf("//")+2,hostUrls[i].lastIndexOf("/"));
System.out.println("第"+(i+1)+"次,在主机:"+url+" 上创建索引,创建时间 "+sdf.format(startDate));
if(i==(hostUrls.length-1)){
list(list,arevageSize*i,arevageSize*(i+1)+remainSize,hostUrls[i]);
}else{
list(list,arevageSize*i,arevageSize*(i+1),hostUrls[i]);
}
Date endDate = new Date();
System.out.println("本次索引结束时间为:"+sdf.format(endDate));
}
}
public void list(List<String> list,int start,int end,String url){
CommonsHttpSolrServer server = getServer(url);
for(int j=start;j<end;j++){
try {
long startMs = System.currentTimeMillis();
hostCreate(list.get(j),server);
long endMs = System.currentTimeMillis();
System.out.println("程序第"+(j+1)+"个目录处理完毕,目录路径:"+list.get(j)+", 耗时"+(endMs-startMs)+"ms");
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void getFile(File fileDirectory,List<String> list){
if(fileDirectory.isDirectory()){
File[] files = fileDirectory.listFiles();
for(File file :files){
getFile(file,list);
}
}else if(fileDirectory.isFile()){
String filePath = fileDirectory.getPath();
String path = filePath.replace('\\', '/');
if(path.endsWith(".cfs")){
int lastIndex = path.lastIndexOf("/");
String directory = path.substring(0,lastIndex);
list.add(directory);
}
}
}
@SuppressWarnings("deprecation")
public void hostCreate(String directory,CommonsHttpSolrServer server)throws CorruptIndexException, IOException{
IndexReader reader = IndexReader.open(directory);
List<BookIndex2> beans = new ArrayList<BookIndex2>();
for(int i=0;i<reader.numDocs();i++){
Document doc = reader.document(i);
BookIndex2 book = new BookIndex2();
book.setZjid(doc.getField("zjid").stringValue());
book.setAddress(doc.getField("address").stringValue());
book.setAuthor(doc.getField("author").stringValue());
book.setbookname(doc.getField("bookname").stringValue());
book.setDxid(doc.getField("dxid").stringValue());
book.setFenlei(doc.getField("fenlei").stringValue());
book.setFenleiurl(doc.getField("fenleiurl").stringValue());
book.setMulu(doc.getField("mulu").stringValue());
book.setPublishDate(doc.getField("publishDate").stringValue());
book.setQwpos(doc.getField("qwpos").stringValue());
book.setSsid(doc.getField("ssid").stringValue());
book.setZhangjie(doc.getField("zhangjie").stringValue());
beans.add(book);
}
createIndex(beans,server);
beans.clear();
reader.close();
}
public void createIndex(List<BookIndex2> beans,CommonsHttpSolrServer server){
try {
server.addBeans(beans);
server.commit();
// server.optimize();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws CorruptIndexException, IOException{
ReaderIndex reader = new ReaderIndex();
String path = "D:\\91";
String[] hosts = new String[] {"http://192.168.169.121:9888/solr","http://192.168.169.121:9088/solr","http://192.168.169.48:9888/solr"};
long startTime = new Date().getTime();
reader.indexDocuements(path,hosts);
long endTime = new Date().getTime();
System.out.println("-------------------");
long ms = (endTime-startTime)%60000-(((endTime-startTime)%60000)/1000)*1000;
System.out.println("全部文档索引完毕,一共用了"+(endTime-startTime)/60000+"分" +
""+((endTime-startTime)%60000)/1000+"秒"+ms+"毫秒");
}
}
附:
开源搜索:所谓开源搜索是指源代码公开的搜索引擎,这就不同于咱们平时一般用的商业搜索引擎比如google ,yahoo ,等,他们这些搜索引擎公司的搜索引擎核心技术是不对外开放的。在现在这个互联网高速发展的信息时代,谁抓住了搜索引擎就抓住了互联网的精髓,那就是客户。有了客户具有了流量 有了用户的粘性就会促使搜索引擎的大大普及。搜索引擎的对人民甚至在某些方面和国家的影响力也越来越多。像google等搜索引擎公司的搜索对用户是免费的但是他的搜索引擎的核心技术不是对外开放的,这就导致搜索引擎具有对在互联网获取信息的垄断。
而开源搜索引擎的出现就给搜索引擎带来了新的希望。
开放源代码搜索引擎为人们学习、研究并掌握搜索技术提供了极好的途径与素材,推动了搜索技术的普及与发展,使越来越多的人开始了解并推广使用搜索技术。使用开源搜索引擎,可以大大缩短构建搜索应用的周期,并可根据应用需求打造个性化搜索应用,甚至构建符合特定需求的搜索引擎系统。搜索引擎的开源,无论是对技术人员还是普通用户,都是一个福音
说道开源搜索引擎不得不说到维基百科。美国时间1月7日,42岁的维基百科(Wikipedia)创始人JimmyWales正式发布维基搜索(WikiaSearch)服务.维基百科的历史以及1400万美元资金的资助名单,让人不敢小觑维基搜索上市,但是这个与众不同的搜索引擎,真的能撼动谷歌、雅虎的地位吗?
美国时间1月7日,42岁的维基百科(Wikipedia)创始人JimmyWales正式发布维基搜索(WikiaSearch)服务.
与7年前维基百科诞生时的默默无闻不同,维基搜索自去年7月威尔斯公开提及后就备受瞩目,大家都想知道这款不同于传统搜索引擎的维基搜索是否会撼动谷歌、雅虎的地位.对此,威尔斯谨慎地表示,他只是将在线百科全书的协作方法引入搜索领域,至少短期内不会威胁到当前主流搜索引擎.是这样吗?
不满,早在意料中
尽管包括中文在内的许多语言还都无法使用,但使用过维基搜索的人会明显感到它的不同.如果没有找到搜索内容,网页会提醒用户“提供帮助”,也就是撰写短文:对关键词进行简要描述,比如定义、同义词、参考短文、图像等.这样,其他用户今后再搜索时就会有更丰富的结果.这有些像维基百科,秉承“众人拾柴火焰高”的原则,借助群众的力量打造一个优秀的搜索引擎.
维基搜索推出3天后,美国的网络杂志《信息周刊》就发表文章表达了不少用户对维基搜索的不满,但这完全在威尔斯的意料之中.作为一种搜索引擎,特别是需要用户大量参与的搜索引擎,维基搜索需要时间提供相关的搜索结果.威尔斯说:“不要指望维基搜索一开始就可以提供能与谷歌相媲美的搜索结果,这根本不可能.1月7日是'软发行',维基搜索需要时间.”
威尔斯是一个沉得住气的人,在他2001年推出维基百科时,几乎没什么人看好这个“网上的百科全书”.1999 年10月20日价值1250美元(大约9000元人民币)的32卷本《大英百科全书》全部上网,供人们免费查询与下载.这在当年是轰动一时的新闻,也给 33岁的威尔斯一个灵感:建立一个真正“开放、免费”的网络百科全书.
事实上,这个灵感在他见到沃德·坎宁安 (WardCunningham)前是很难实现的.威尔斯学金融出身,他在美国印第安那大学取得经济学博士学位,研究方向是期权定价.当他还在芝加哥的外汇市场如鱼得水时,美国人坎宁安开发了一种在Web基础上对文本进行浏览、创建、更改的社群协作式写作技术,并把它命名为wiki,意为“快点快点”的夏威夷语缩写.
2001年,威尔斯把wiki技术变成了维基百科全书,英文版的维基百科全书于当年1月15日正式问世.在短短一个月时间内,维基的条目达到了200条,一年之后增加到1.8万条.2004年9月,维基百科全书的条目达到100 万条,此时它的投资总额达到50万美元,其中大部分是威尔士的个人投资,主要源于他早年在芝加哥金融市场的建树.
维基百科经过时间的长期沉淀,体现出了巨大价值.威尔斯凭借社区的影响力把维基百科打造成了一家知名的网络信息源.他说:“维基百科刚开始也是一无所有,经过7年的发展壮大,今天维基百科已经成了互联网领域第8大网站.如果用户有一种拥有者的感觉,那么他们就会继续使用该工具,这就是我们所要努力的方向.”
令人不敢小觑
回顾维基百科的历史,让人不敢小觑威尔斯的每一步探索.他在2004年成立了营利性公司WikiaInc.( 而维基百科是非营利性的),提供可以让任何人轻松搭建维基系统的软件平台,维基搜索就是该公司的项目之一.威尔斯在进军搜索领域前,并不指望叫板谷歌.但他有着自己的打算:改变用户网络搜索的方式.
维基搜索1400万美元资金的资助名单似乎意味着业界十分看好这款搜索引擎:亚马逊(提供1000万美元)、贝西默风险投资合伙人公司(BessemerVenturePartners)、网景通讯公司 (NetscapeCommunications) 创始人之一马克·安德森(MarcAndreesen)、美国第六大社交网站LinkedIn的创始人之一里德·霍夫曼(ReidHoffman)、莲花发展公司(LotusDevelopment)的创始人兼电子前沿基金会(ElectronicFrontierFoundation) 的创始人之一米切尔·卡普尔(MitchKapor).
20款开源搜索引擎系统
一些开源搜索引擎系统介绍,包含开源Web搜索引擎和开源桌面搜索引擎。
Sphider
Sphider是一个轻量级,采用PHP开发的web spider和搜索引擎,使用mysql来存储数据。可以利用它来为自己的网站添加搜索功能。Sphider非常小,易于安装和修改,已经有数千网站在使用它。
RiSearch PHP
RiSearch PHP是一个高效,功能强大的搜索引擎,特别适用于中小型网站。RiSearch PHP非常快,它能够在不到1秒钟内搜索5000-10000个页面。RiSearch是一个索引搜索引擎,这就意味着它先将你的网站做索引并建立一个数据库来存储你网站所有页面的关键词以便快速搜索。Risearch是全文搜索引擎脚本,它把所有的关键词都编成一个文档索引除了配置文件里面的定义排除的关键词。 RiSearch使用经典的反向索引算法(与大型的搜索引擎相同),这就是为什么它会比其它搜索引擎快的原因。
PhpDig是一个采用PHP开发的Web爬虫和搜索引擎。通过对动态和静态页面进行索引建立一个词汇表。当搜索查询时,它将按一定的排序规则显示包含关键字的搜索结果页面。PhpDig包含一个模板系统并能够索引PDF,Word,Excel,和PowerPoint文档。PHPdig适用于专业化更强、层次更深的个性化搜索引擎,利用它打造针对某一领域的垂直搜索引擎是最好的选择。
OpenWebSpider
OpenWebSpider是一个开源多线程Web Spider(robot:机器人,crawler:爬虫)和包含许多有趣功能的搜索引擎。
Egothor
Egothor是一个用Java编写的开源而高效的全文本搜索引擎。借助Java的跨平台特性,Egothor能应用于任何环境的应用,既可配置为单独的搜索引擎,又能用于你的应用作为全文检索之用。
Nutch 是一个开源Java 实现的搜索引擎。它提供了我们运行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬虫。
Apache Lucene是一个基于Java全文搜索引擎,利用它可以轻易地为Java软件加入全文搜寻功能。Lucene的最主要工作是替文件的每一个字作索引,索引让搜寻的效率比传统的逐字比较大大提高,Lucen提供一组解读,过滤,分析文件,编排和使用索引的API,它的强大之处除了高效和简单外,是最重要的是使使用者可以随时应自己需要自订其功能。
Oxyus
是一个纯java写的web搜索引擎。
BDDBot
BDDBot是一个简单的易于理解和使用的搜索引擎。它目前在一个文本文件(urls.txt)列出的URL中爬行,将结果保存在一个数据库中。它也支持一个简单的Web服务器,这个服务器接受来自浏览器的查询并返回响应结果。它可以方便地集成到你的Web站点中。
Zilverline
Zilverline是一个搜索引擎,它通过web方式搜索本地硬盘或intranet上的内容。Zilverline可以从PDF, Word, Excel, Powerpoint, RTF, txt, java, CHM,zip, rar等文档中抓取它们的内容来建立摘要和索引。从本地硬盘或intranet中查找到的结果可重新再进行检索。Zilverline支持多种语言其中包括中文。
XQEngine
XQEngine用于XML文档的全文本搜索引擎。利用XQuery做为它的前端查询语言。它能够让你查询XML文档集合通过使用关键字的逻辑组合。有点类似于Google与其它搜索引擎搜索HTML文档一样。XQEngine只是一个用Java开发的很紧凑的可嵌入的组件。
MG4J可以让你为大量的文档集合构建一个被压缩的全文本索引,通过使内插编码(interpolative coding)技术。
JXTA Search
JXTA Search是一个分布式的搜索系统。设计用在点对点的网络与网站上。
YaCy基于p2p的分布式Web搜索引擎。同时也是一个Http缓存代理服务器。这个项目是构建基于p2p Web索引网络的一个新方法。它可以搜索你自己的或全局的索引,也可以Crawl自己的网页或启动分布式Crawling等。
Red-Piranha
Red-Piranha是一个开源搜索系统,它能够真正”学习”你所要查找的是什么。Red-Piranha可作为你桌面系统(Windows,Linux与Mac)的个人搜索引擎,或企业内部网搜索引擎,或为你的网站提供搜索功能,或作为一个P2P搜索引擎,或与wiki结合作为一个知识/文档管理解决方案,或搜索你要的RSS聚合信息,或搜索你公司的系统(包括SAP,Oracle或其它任何Database/Data source),或用于管理PDF,Word和其它文档,或作为一个提供搜索信息的WebService或为你的应用程序(Web,Swing,SWT,Flash,Mozilla-XUL,PHP, Perl或c#/.Net)提供搜索后台等等。
LIUS
LIUS是一个基于Jakarta Lucene项目的索引框架。LIUS为Lucene添加了对许多文件格式的进行索引功能如:Ms Word,Ms Excel,Ms PowerPoint,RTF,PDF,XML,HTML,TXT,Open Office序列和JavaBeans.针对JavaBeans的索引特别有用当我们要对数据库进行索引或刚好用户使用持久层ORM技术如:Hibernate,JDO,Torque,TopLink进行开发时。
Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。文档通过Http利用XML加到一个搜索集合中。查询该集合也是通过 http收到一个XML/JSON响应来实现。它的主要特性包括:高效、灵活的缓存功能,垂直搜索功能,高亮显示搜索结果,通过索引复制来提高可用性,提供一套强大Data Schema来定义字段,类型和设置文本分析,提供基于Web的管理界面等。
Paoding
Paoding中文分词是一个使用Java开发的,可结合到Lucene应用中的,为互联网、企业内部网使用的中文搜索引擎分词组件。 Paoding填补了国内中文分词方面开源组件的空白,致力于此并希翼成为互联网网站首选的中文分词开源组件。 Paoding中文分词追求分词的高效率和用户良好体验。
Carrot2
Carrot2是一个开源搜索结果分类引擎。它能够自动把搜索结果组织成一些专题分类。Carrot2提供的一个架构能够从各种搜索引擎(YahooAPI、GoogleAPI、MSN Search API、eTools Meta Search、Alexa Web Search、PubMed、OpenSearch、Lucene index、SOLR)获取搜索结果。
Regain
regain是一款与Web搜索引擎类似的桌面搜索引擎系统,其不同之处在于regain不是对Internet内容的搜索,而是针对自己的文档或文件的搜索,使用regain可以轻松地在几秒内完成大量数据(许多个G)的搜索。Regain采用了Lucene的搜索语法,因此支持多种查询方式,支持多索引的搜索及基于文件类型的高级搜索,并且能实现URL重写及文件到HTTP的桥接,并且对中文也提供了较好的支持。
Regain提供了两种版本:桌面搜索及服务器搜索。桌面搜索提供了对普通桌面计算机的文档与局域网环境下的网页的快速搜索。服务器版本主要安装在Web服务器上,为网站及局域网环境下的文件服务器进行搜索。
转载自:http://ronxin999.blog.163.com/blog/static/4221792020116642323648/?suggestedreading