利用SOLR搭建企业搜索平台
3)core
The <core> tag accepts two attributes:
name - The registered core name. This will be how the core is accessed.
instanceDir - The solr.home directory for a given core.
dataDir - The data directory for a given core. The default is <instanceDir>/data . It can take an absolute path or a relative path w.r.t instanceDir . Solr1.4
4)property
The <property> tag accepts two attributes:
name - The name of the property
value - The value of the property
由于E文过于简单,所以就不翻译了!??????????????????????????????????????????????????????????????? 利用SOLR搭建企业搜索平台 之五(solrj)
比如提交一个xml,采用post方式,尽管有些文章说了可以采用httpclient。但是我那个时候,还不是很理解,当然现在看来其实也没有什么了。但是对于一个刚入门solr的初学者,我想讲讲关于solr1.3的 solrj( sorlr J 目前使用二进制的格式作为默认的格式。对于solr1.2的用户通过显示的设置才能使用XML格式。)!
先上一个例子:
Java代码
public static final String SOLR_URL = "http://localhost/solr/core0";
public static void commit() {
Date date = new Date();
SolrServer solr = null;
try {
solr = new CommonsHttpSolrServer(SOLR_URL);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
for (int i = 0; i < 10000; i++) {
SolrInputDocument sid = new SolrInputDocument();
sid.addField("id", i);
sid.addField("name", "struts+hibernate+spring 开发大全" + i);
sid.addField("summary", "三种框架的综合应用" + i);
sid.addField("author", "李良杰" + i);
sid.addField("date", new Date());
sid.addField("content", "高级应用类书籍" + i);
sid.addField("keywords", "SSH" + i);
try {
solr.add(sid);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(i);
if (i == 999)
System.out.println((new Date().getTime() - date.getTime()) / 60000 + "分钟");
}
try {
solr.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} 上面这段代码的意思是:利用for提交10000个document,并打印提交10000所需的时间。
1》CommonsHttpSolrServer 使用HTTPClient 和solr服务器进行通信。
2》CommonsHttpSorlrServer 允许设置链接属性。
Java代码
?? server.setSoTimeout(1000); // socket read timeout
server.setConnectionTimeout(100);
server.setDefaultMaxConnectionsPerHost(100);
server.setMaxTotalConnections(100);
server.setFollowRedirects(false); // defaults to false
// allowCompression defaults to false.
// Server side must support gzip or deflate for this to have any effect.
server.setAllowCompression(true);
server.setMaxRetries(1); // defaults to 0. > 1 not recommended.
3》实现SolrServer接口的另一个类:EmbeddedSorrServer,它不需要http连接。
4》在构造document的时候,可以一个一个添加到solrServer,也可以构建一个包含document的Collection,将Collection添加到solrServer,然后commit。
5》也可以构造一个跟document匹配的JavaBean进行提交
使用 java 注释创建java bean。@Field ,可以被用在域上,或者是setter方法上。如果一个域的名称跟bean的名称是不一样的,那么在java注释中填写别名,具体的,可以参照下面的域categories
Java代码
import org.apache.solr.client.solrj.beans.Field;
public class Item {
@Field
String id;
@Field("cat")
String[] categories;
@Field
List<String> features;
} java注释也可以使用在setter方法上,如下面的例子:
Java代码
@Field("cat")
public void setCategory(String[] c){
this.categories = c;
}
这里应该要有一个相对的,get方法(没有加java注释的)来读取属性
Java代码
Item item = new Item();
item.id = "one";
item.categories = new String[] { "aaa", "bbb", "ccc" };
添加给solr
Java代码
server.addBean(item);
将多个bean提交给solr
Java代码
List<Item> beans ;
//add Item objects to the list
server.addBeans(beans);
注意: 你可以重复使用SolrServer,这样可以提高性能。
6》
Java代码
public static void update() {
SolrServer solrServer = null;
try {
solrServer = new CommonsHttpSolrServer(SOLR_URL);
} catch (MalformedURLException e) {
e.printStackTrace();
}
UpdateRequest updateRequest = new UpdateRequest();
SolrInputDocument sid = new SolrInputDocument();
sid.addField("id", 100000);
sid.addField("name", "struts+hibernate+spring 开发大全");
sid.addField("summary", "三种框架的综合应用");
sid.addField("author", "李良杰");
sid.addField("date", new Date());
sid.addField("content", "高级应用类书籍");
sid.addField("keywords", "SSH");
updateRequest.setAction(UpdateRequest.ACTION.COMMIT, false, false);
updateRequest.add(sid);
try {
UpdateResponse updateResponse = updateRequest.process(solrServer);
System.out.println(updateResponse.getStatus());
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} 提交一个document,采用更新方式,注意:
Java代码
updateRequest.setAction(UpdateRequest.ACTION.COMMIT, false, false);
7》
Java代码
public static void query() {
SolrServer solr = null;
try {
solr = new CommonsHttpSolrServer(SOLR_URL);
} catch (MalformedURLException e) {
e.printStackTrace();
return;
}
// http://localhost:8983/solr/spellCheckCompRH?q=epod&spellcheck=on&spellcheck.build=true
ModifiableSolrParams params = new ModifiableSolrParams();
params.set("qt", "/spellCheckCompRH");
params.set("q", "编程");
params.set("spellcheck", "on");
params.set("spellcheck.build", "true");
QueryResponse response = null;
try {
response = solr.query(params);
} catch (SolrServerException e) {
e.printStackTrace();
return;
}
System.out.println("response = " + response);
}
这是一个查询方法。关键字:“编程”。关于查询的关键字,请参见slor wiki http://wiki.apache.org/solr/QueryParametersIndex,或等待我的博客更新,在后面会有篇文章详细讲这个问题!
8》给solr的索引文件手动进行优化,
solr.optimize();
9》solrJ 提供了一组API,来帮助我们创建查询,下面是一个faceted query的例子。
SolrServer server = getSolrServer();
SolrQuery solrQuery = new SolrQuery().setQuery("ipod").setFacet(true).setFacetMinCount(1).setFacetLimit(8). addFacetField("category").addFacetField("inStock");
QueryResponse rsp = server.query(solrQuery);
所有的 setter/add 方法都是返回它自己本身的实例,所以就像你所看到的一样,上面的用法是链式的。??????????????????????????????????????????????? 利用SOLR搭建企业搜索平台 之六(solr查询参数说明)
在做solr查询的时候,solr提供了很多参数来扩展它自身的强大功能!以下是使用频率最高的一些参数!
具体请看:
1.常用
q - 查询字符串,必须的。查询语句(类似SQL) 相关详细的操作还需lucene 的query 语法
fl - 指定返回那些字段内容,用逗号或空格分隔多个。
start - 返回第一条记录在完整找到结果中的偏移位置,0开始,一般分页用。
rows - 指定返回结果最多有多少条记录,配合start来实现分页。
sort - 排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 。示例:(score desc, price asc)表示先 “score” 降序, 再 “price” 升序,默认是相关性降序。
wt - (writer type)指定输出格式,可以有 xml, json, php, phps, 后面 solr 1.3增加的,要用通知我们,因为默认没有打开。
fl表示索引显示那些field(*表示所有field, score 是solr 的一个匹配热度)
q.op 表示q 中 查询语句的 各条件的逻辑操作 AND(与) OR(或)
hl 是否高亮
hl.fl 高亮field
hl.snippets 不太清楚(反正是设置高亮3就可以了)
hl.simple.pre 高亮前面的格式
hl.simple.post 高亮后面的格式
facet 是否启动统计
facet.field 统计field
fq - (filter query)过虑查询,作用:在q查询符合结果中同时是fq查询符合的,例如:q=mm&fq=date_time:[20081001 TO 20091031],找关键字mm,并且date_time是20081001到20091031之间的。官方文档:http://wiki.apache.org/solr/Comm ... ec487758577506d6002
2.不常用
q.op - 覆盖schema.xml的defaultOperator(有空格时用"AND"还是用"OR"操作逻辑),一般默认指定
df - 默认的查询字段,一般默认指定
qt - (query type)指定那个类型来处理查询请求,一般不用指定,默认是standard。
3.其它
indent - 返回的结果是否缩进,默认关闭,用 indent=true|on 开启,一般调试json,php,phps,ruby输出才有必要用这个参数。
version - 查询语法的版本,建议不使用它,由服务器指定默认值。??利用SOLR搭建企业搜索平台 之七(solr使用问题集)
某日,突发奇想,想写这么一个博客,希望记录下所有在solr中使用的毛病。而且我希望广大的看友们也能一起来说说你们平时遇到的各种错误,这样大家才能一起更好的进步!
话不多说,进入正题
1》solr 做索引时报 Lock obtain timed out: SingleInstanceLock: write.lock
有个频繁做索引的应用,它同时也对外提供搜索服务。大部分是 solr 1.3 的默认配置。solr 做索引,有时候报:
Xml代码
2009-7-13 9:48:06 org.apache.solr.common.SolrException log
严重: org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: SingleInstanceLock: write.lock
at org.apache.lucene.store.Lock.obtain(Lock.java:85)
at org.apache.lucene.index.IndexWriter.init(IndexWriter.java:1140)
at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:938)
at org.apache.solr.update.SolrIndexWriter.<init>(SolrIndexWriter.java:116)
...
是写锁取不到。但重启 solr 又可以正常做,主要是运行时间长了就报这个错了。还是看下配置吧。
看到 solr 1.3 默认的配置是:
Xml代码
<indexDefaults>
<!-- ... -->
<!--
This option specifies which Lucene LockFactory implementation to use.
single = SingleInstanceLockFactory - suggested for a read-only index
or when there is no possibility of another process trying
to modify the index.
native = NativeFSLockFactory
simple = SimpleFSLockFactory
(For backwards compatibility with Solr 1.2, 'simple' is the default
if not specified.)
-->
<lockType>single</lockType>
</indexDefaults> ?? 默认锁是 single ,只读的。solr 1.2 是 simple,把它改回去了,运行了几天,没事。
2》lucene & solr optimize 索引后结果与平台有点关系
昨日做索引的程序重构下,测试 optimize 索引(在原有数据基础上提交索引)时,在开发的机器(windows)里总是会有两段索引,要再 optimize 才只是一个索引段,当然不是设置 maxSegments=2。反复运行还是如此,为了说明是否写的程序有问题,就用 solr 自带的 post.sh (或 post.jar)提交 optimize。结果还是有两段,再提交一次optimize 才是一个段。这问题……
旧的程序运行得很正常,看了下它也没有提交两次优化。然后把新的程序也放到服务器(linux)上运行,结果是只有一个段。
恩,可以认为是与文件系统有关,optimize 的时候是先新生成一段,然后再删除旧的索引,windows 可能是这样在运行期间与文件关联着删除不了旧的。linux 可能是不用(不打开)文件就可以删除。现只能这样简单解释。
3》换 solr 里的 lucene 包
solr 1.3 发布的时候,lucene 2.4还没有正式发布,其的 lucene 是开发版,现在lucene 2.4早已发布,那就换上新的 lucene 吧。
下载 solr 1.3 http://labs.xiaonei.com/apache-m ... ache-solr-1.3.0.zip 和 lucene 2.4 http://labs.xiaonei.com/apache-m ... va/lucene-2.4.0.zip 到目录如e:/search/,
把 e:/search/apache-solr-1.3/lib 目录下的 lucene 相关的*.jar删除:
lucene-analyzers-2.4-dev.jar
lucene-core-2.4-dev.jar
lucene-highlighter-2.4-dev.jar
lucene-memory-2.4-dev.jar
lucene-queries-2.4-dev.jar
lucene-snowball-2.4-dev.jar
lucene-spellchecker-2.4-dev.jar
从 e:/search/lucene-2.4/(或contrib/)目录下找到对应的放到solr-1.3/lib下
然后构建 solr,到e:/search/apache-solr-1.3目录,ant dist-war
4》solr q查询容错性
当solr接收没q参数(或q参数值为空)请求时,会报错。报错十分讨厌,对开发调试时才比较有用,但实际运行环境报错就不太好了,java异常可能有点性能消耗,那干脆就返回正常的结果好了(只是结果里没有找到的数据)。
solr 1.3 可以写个组件去做。判断到空的时候,加一个q参数,其值为在索引里没有的数据。这样就可以返回没有数据的结果。
其实这样实现还是比较麻烦。可以在 solrconfig.xml的requestHandler里加一个默认参数。如q=abcdefghijk。配置如下:
Xml代码
<requestHandler name="standard" />
定义一个 handler 使用上面的搜索组件:
Xml代码
<requestHandler name="collapse" height="275" width="550" src="/img/2012/06/24/0928004278.png">0 && image.height<0){if(image.width<=700){this.width=700;this.height=image.height*700/image.width;}}" border=0<
六.启动TOMCAT,输入地址进行导入,导入分为很多模式:我选用的全部倒入模式。
http://localhost/solr/dataimport?command=full-import
结果:
00C:\solr-tomcat\solr\db\conf\db-data-config.xmlfull-importidle1202009-09-0521:28:08Indexing completed. Added/Updated: 2 documents. Deleted 0documents.2009-09-05 21:28:092009-09-05 21:28:090:0:0.579This responseformat is experimental. It is likely to change in the future.
七.在去查询你刚才提交的数据,搞定。
最后在说说这个功能。上面的例子只不过是很简单的一个部分。针对solr的MultiCore,通过配置db-data-config.xml也可以实现,还有多表,或者多表关联等等操作只要在db-data-config.xml配置清楚都可以进行数据的导入。
在solr1.4中还有更多的扩展功能,这些功能为重建索引提供能很方便的操作。而且,datasource不单单指的是database,可以是xml文件,还可以是来自网络上的等等。??利用SOLR搭建企业搜索平台 之十一(中文分词之IK)
在经过使用了庖丁以后,这里说说怎么将目前很火很流行的IK集成进SOLR,其实方法真的很简单,比paoding方便不少。这里很感谢IK的作者,蓝山咖啡,很感谢你为中文分词做出的贡献。 作者博客:http://linliangyi2007.javaeye.com
入正题:
1》请先去作者博客参看IK下载地址,主要就是一个IKAnalyzer3.1.1Stable.jar。我这里用的是最新版!
Java代码 package com.yeedoo.slor.tokenizer;
import java.io.Reader;
import org.apache.lucene.analysis.TokenStream;
import org.apache.solr.analysis.BaseTokenizerFactory;
import org.wltea.analyzer.lucene.IKAnalyzer;
public class ChineseTokenizerFactory extends BaseTokenizerFactory {
@Override
public TokenStream create(Reader reader) {
return new IKAnalyzer().tokenStream("text", reader);
}
}
从代码就可以看得出来真的很方便!将它打包放入solr.war中同时还有IK的jar包。如果你不想打包,请去附件下载已经打好的包。
2》配置文件
Xml代码 <fieldType name="text" height="431" width="700" src="/img/2012/06/24/0928004279.png">