一、SolrJ的使用
- 导入相关jar包,打开solr-3.5/dist/solrj-lib,找到下面五个文件:commons-codec-1.5.jar,commons-httpclient-3.1.jar,commons-io-1.4.jar,jcl-over-slf4j-1.5.5.jar,slf4j-api-1.5.5.jar。再找到dist路径下的apache-solr-core-3.5.0.jar和apache-solr-solrj.3.5.0.jar。
- 创建测试类SolrJTest.class。
二、相关代码
删除所有索引
CommonsHttpSolrServer commonsHttpSolrServer = new CommonsHttpSolrServer(solrServerUrl);
// 删除所有数据并提交
commonsHttpSolrServer.deleteByQuery("*:*");
commonsHttpSolrServer.commit();
创建文档
// 添加文档并提交
SolrInputDocument solrInputDocument = new SolrInputDocument();
// 添加Field的时候,这里必须有一个主键id,这里的类型也要是String的
solrInputDocument.addField("id", "1");
solrInputDocument.addField("title", "这是我的第一个SolrJ的程序");
// 会发现content这一行报错,为什么呢?因为在默认的schema.xml中没有content的field
// solrInputDocument.addField("content","这个程序能不能跑起来呢?");
commonsHttpSolrServer.add(solrInputDocument);
commonsHttpSolrServer.commit();
打开Luke查看分词结果,结果如下图,因为没有使用中文分词器,所以几乎没效果。
在schema.xml中加入自己定义的Field,并指定type为中文分词器的type。分别在types标签最上面和fields标签最上面加入下面的代码,标注IK分词器和自定义的域。重启Tomcat服务器。这里注意修改文件的时候别改错了,蠢蠢的我就改错了,改成了example中的schema.xml,这肯定不起作用啊,需要修改home下的schema.xml文件才生效。
<!--IK分词器,加在types最上面-->
<fieldType name="text" class="solr.TextField" >
<analyzer type="index">
<tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" useSmart ="false"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" useSmart ="false"/>
</analyzer>
</fieldType>
<!-- 自定义的Field,加在fields最上面,这里的type="text"对应上面的name="text" -->
<field name="msg_title" type="text" store="true" indexed="true" />
<field name="msg_content" type="text" store="true" indexed="true" />
打开Luke查看结果,可以看到分词起作用了。
我们在搜索的时候,希望既搜索msg_title域,又搜索msg_content域,我们需要在Query String中输入“msg_title:程序 msg_content:程序”来实现or的效果,写法上还是比较麻烦的,所以Solr给我们提供了一个方法。在schema.xml的合适位置加上下面的代码。注意这里多了一个multiValued,这个multiValued别写错了,是大小写敏感的,一开始写成了multivalued,结果不起作用,这个的作用相当于把msg_content和msg_title拷贝到了msg_all中了。以后就使用msg_all来搜索了。重启Tomcat服务器。重新建立添加文档后,在Query String中输入“msg_all:程序”搜索就可以既查询title,又查询content了。
<!-- multiValued="true"表示这个域是允许多个值的 -->
<field name="msg_all" type="text" store="false" indexed="true" multiValued="true" />
<!-- 指定msg_all的copyField -->
<copyField source="msg_title" dest="msg_all" />
<copyField source="msg_content" dest="msg_all" />
可是,我们在搜索的时候,通常不会输入某个域吧?所以这里可以指定某个域是默认搜索域,即在schema.xml中搜索“defaultSearchField”节点。修改其中的值为“msg_all”,重启Tomcat,重新添加文档,在Query String中输入“程序”。发现可以搜索到,说明配置的默认域生效了。
三、项目代码
package com.wsy;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.junit.Test;
import java.io.IOException;
import java.net.MalformedURLException;
public class SolrJTest {
private final static String solrServerUrl = "http://localhost:8080/solr";
@Test
public void test() {
try {
// 创建SolrServer对象(CommonsHttpSolrServer和EmbeddedSolrServer)
// CommonsHttpSolrServer需要启动web服务器,通过HTTP请求获取数据
// EmbeddedSolrServer是内嵌式的,可以不启动HTTP来获取数据,只需要导入包,指定home目录就可以了,但是底层还是依托于HTTP服务的
CommonsHttpSolrServer commonsHttpSolrServer = new CommonsHttpSolrServer(solrServerUrl);
// 删除所有数据并提交
// commonsHttpSolrServer.deleteByQuery("*:*");
// commonsHttpSolrServer.commit();
// 添加文档并提交
SolrInputDocument solrInputDocument = new SolrInputDocument();
// 添加Field的时候,这里必须有一个主键id,这里的类型也要是String的
// id是唯一主键,当有相同的id的时候,后面的会把前面的覆盖掉
solrInputDocument.addField("id", "1");
solrInputDocument.addField("msg_title", "这是我的第一个SolrJ的程序");
solrInputDocument.addField("msg_content", "这个程序能不能跑起来呢?");
commonsHttpSolrServer.add(solrInputDocument);
commonsHttpSolrServer.commit();
// 10分钟
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}