package com.jadyer.solrj;

import java.util.ArrayList;
import java.util.List; import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument; import com.jadyer.model.MyMessage; /**
* 【Lucene3.6.2入门系列】第14节_SolrJ操作索引和搜索文档以及整合中文分词
* @see -------------------------------------------------------------------------------------------------------------------------
* @see 通过schema.xml使得Solr与中文分词进行整合
* @see 0)默认solr定义的大量域都不支持中文分词,如果我们要加中文分词的支持,那么首先要加的就是<types><fieldType/></types>
* @see 下面以MMSeg4j-1.8.5为例,描述Solr与中文分词器的整合方式(其核心就是在schema.xml中配置fieldType)
* @see 关于MMSeg4j的介绍,详见http://blog.csdn.net/jadyer/article/details/10049525
* @see 1)将mmseg4j-all-1.8.5.jar拷到D:\Develop\apache-solr-3.6.2\server\solr\WEB-INF\lib\文件夹中
* @see 2)新建D:\Develop\apache-solr-3.6.2\home\dic\文件夹
* @see 3)将mmseg4j-1.8.5.zip\data\文件夹中的词典文件拷贝到D:\Develop\apache-solr-3.6.2\home\dic\
* @see 4)在schame.xml中添加中文分词的fieldType定义
* @see 通常中文分词的工具包中都会提供README.txt文件,里面会描述扩展solr时需要配置的fieldType
* @see 同理将mmseg4j-1.8.5.zip中的README.txt打开,拷贝里面描述的三个fieldType到schema.xml中第68行
* @see 5)确认并修改这三个fileType中的dicPath属性值为"dic"(这里的dic其实指的就是第二步新建的dic文件夹)
* @see 6)最后测试一下中文分词效果
* @see 在solr控制台上(http://127.0.0.1:8088/solr/admin/)点击蓝色粗体的[ANALYSIS]
* @see 然后在Field Analysis下面将Field下拉框修改为type,并在右面文本框输入text_general(即schema.xml中定义的fieldType)
* @see 接着在Field Value(Index)右面的文本框中输入测试文本'我来自中国黑龙江省哈尔滨市巴彦县兴隆镇长春乡民权村4队'
* @see 再点击下方的Analyze按钮,我们就会发现text_general的分词情况了,然后我们再修改text_general为刚才自定义的textComplex,就看到效果啦
* @see 另外也可以勾选Field Value(Index)下面的verbose output选框,这样也会将分词的各个属性(position,Offset,type等等)一并显示出来
* @see -------------------------------------------------------------------------------------------------------------------------
* @see 本例中合计用到9个jar,如下所示
* @see apache-solr-core-3.6.2.jar
* @see apache-solr-solrj-3.6.2.jar
* @see commons-codec-1.6.jar
* @see commons-io-2.1.jar
* @see httpclient-4.1.3.jar
* @see httpcore-4.1.4.jar
* @see httpmime-4.1.3.jar
* @see jcl-over-slf4j-1.6.1.jar
* @see slf4j-api-1.6.1.jar
* @see -------------------------------------------------------------------------------------------------------------------------
* @create Aug 7, 2013 11:06:20 PM
* @author 玄玉<http://blog.csdn.net/jadyer>
*/
public enum HelloSolrJ {
INSTANCE; private SolrServer server; private HelloSolrJ(){
//创建SolrServer对象,它有两个线程安全的子类EmbeddedSolrServer和CommonsHttpSolrServer
//EmbeddedSolrServer-----内嵌式的,不需要启动Web服务器
//CommonsHttpSolrServer--需要启动Web服务器,它是通过HTTP请求来获取数据的
//CommonsHttpSolrServer已不推荐直接使用了,而是推荐使用HttpSolrServer类
//同样的StreamingUpdateSolrServer也不推荐使用了,推荐使用ConcurrentUpdateSolrServer
server = new HttpSolrServer("http://127.0.0.1:8088/solr");
} /**
* 删除全部索引
*/
public void deleteAllIndex(){
try {
//删除所有的索引,删除完记得commit才能生效
server.deleteByQuery("*:*");
server.commit();
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 添加索引
* @see 这里之所以没有硬编码指定my_title和my_content的中文分词器
* @see 是由于schema.xml中在定义这俩<field>时已通过type属性指定了中文分词器
*/
public void addIndex(){
List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
for(int i=1; i<4; i++){
SolrInputDocument doc = new SolrInputDocument();
//对于Solr而言,默认的id是唯一的主键(如果我们没有自定义主键的话),当多次添加的时候,最后添加的相同id的域会覆盖已有的
doc.addField("id", Integer.toString(i));
//这里使用的是自定义的Field,所以就需要在schema.xml中为其添加<field>描述,并通过type属性指定其使用的分词器
doc.addField("my_title", "这是我的第" + i + "个SolrJ程序");
doc.addField("my_content", "my第" + i + "个SolrJ程序的运行情况");
docs.add(doc);
}
try {
//可以只添加一个Document,也可以一次添加多个Document,这里添加多个
server.add(docs);
//commit后方能生效,否则搜索到的还是add前的索引信息
server.commit();
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 使用JavaBean来添加索引
*/
public void addIndexByBean(){
List<MyMessage> msgs = new ArrayList<MyMessage>();
//由于MyMessage()的第三个参数允许传入多个值,此时就要在Solr的schema.xml中配置<field my_content multiValued="true"/>支持多值域
//并且在MyMessage.java中要使用@Field注解标注,可以标注在属性或setter方法上,并通过注解的默认值来指定所要存储的Field的名字
msgs.add(new MyMessage("4", "这是我的第4个SolrJ程序", new String[]{"第4个SolrJ程序诞生于中国", "它是通过SolrJ OF JavaBean4诞生添加的"}));
msgs.add(new MyMessage("5", "这是我的第5个SolrJ程序", new String[]{"第5个SolrJ程序诞生于哈尔滨", "它是通过SolrJ OF JavaBean5诞生添加的"}));
try {
server.addBeans(msgs);
server.commit();
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 搜索文档
*/
public void searchFile(){
//设置查询字符串
SolrQuery query = new SolrQuery("my_content:诞生");
//设置了setStart和setRows就可以实现分页效果了
query.setStart(0);
query.setRows(3);
QueryResponse resp = null;
try {
resp = server.query(query);
} catch (SolrServerException e) {
e.printStackTrace();
}
//搜索出来的结果都保存在SolrDocumentList中
SolrDocumentList sdl = resp.getResults();
//这里获取到的是搜索到的总数量,与query.setRows(3)无关
System.out.println("本次搜索到[" + sdl.getNumFound() + "]条数据");
for(SolrDocument sd : sdl){
//System.out.println(sd)会输出SolrDocument[{id=4, my_title=这是我的第4个SolrJ程序, my_content=[第4个....于中国, 它是....进来的]}]
System.out.println("my_title=" + sd.getFieldValue("my_title") + " my_content=" + sd.getFieldValue("my_content"));
}
} /**
* 使用JavaBean接收文档搜索结果
*/
public void searchFileByBean(){
SolrQuery query = new SolrQuery("id:*");
query.setStart(0);
query.setRows(3);
QueryResponse resp = null;
try {
resp = server.query(query);
} catch (SolrServerException e) {
e.printStackTrace();
}
List<MyMessage> list = resp.getBeans(MyMessage.class);
//这里获取到的不是搜索到的总数量,而是与query.setRows(3)有关的值
//若实际的SolrQuery("id:*")能搜索到5条,则这里得到的就是3,若实际能搜索到的是2条,则这里得到的就是2条
System.out.println("本次搜索到[" + list.size() + "]条数据");
for(MyMessage msg : list) {
System.out.println(msg.getTitle() + " " + msg.getContent()[0]);
}
}
}

下面是用到的JavaBean类

package com.jadyer.model;

import org.apache.solr.client.solrj.beans.Field;

public class MyMessage {
@Field
private String id;
@Field("my_title")
private String title;
@Field("my_content")
private String[] content; /*-- 三个属性的setter和getter略 --*/ public MyMessage() {} public MyMessage(String id, String title, String[] content) {
this.id = id;
this.title = title;
this.content = content;
}
}

最后是JUnit4.x写的一个小测试

package com.jadyer.test;

import org.junit.Test;

import com.jadyer.solrj.HelloSolrJ;

public class HelloSolrJTest {
@Test
public void deleteAllIndex(){
HelloSolrJ.INSTANCE.deleteAllIndex();
} @Test
public void addIndexAndSearchFile(){
HelloSolrJ.INSTANCE.addIndex();
HelloSolrJ.INSTANCE.searchFile();
} @Test
public void addIndexAndSearchFileByBean(){
HelloSolrJ.INSTANCE.addIndexByBean();
HelloSolrJ.INSTANCE.searchFileByBean();
}
}

【Lucene3.6.2入门系列】第14节_SolrJ操作索引和搜索文档以及整合中文分词的更多相关文章

  1. 【Lucene3.6.2入门系列】第04节_中文分词器

    package com.jadyer.lucene; import java.io.IOException; import java.io.StringReader; import org.apach ...

  2. 【Lucene3.6.2入门系列】第05节_自定义停用词分词器和同义词分词器

    首先是用于显示分词信息的HelloCustomAnalyzer.java package com.jadyer.lucene; import java.io.IOException; import j ...

  3. 【Lucene3.6.2入门系列】第03节_简述Lucene中常见的搜索功能

    package com.jadyer.lucene; import java.io.File; import java.io.IOException; import java.text.SimpleD ...

  4. 【Lucene3.6.2入门系列】第15节_SolrJ高亮

    package com.jadyer.solrj; import java.util.ArrayList; import java.util.List; import java.util.Map; i ...

  5. 【Lucene3.6.2入门系列】第10节_Tika

    首先贴出来的是演示了借助Tika创建索引的HelloTikaIndex.java PS:关于Tika的介绍及用法,详见下方的HelloTika.java package com.jadyer.luce ...

  6. ElasticSearch入门 第四篇:使用C#添加和更新文档

    这是ElasticSearch 2.4 版本系列的第四篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  7. ABP入门系列(14)——应用BootstrapTable表格插件

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 引言 之前的文章ABP入门系列(7)--分页实现讲解了如何进行分页展示,但其分页展示仅适用于 ...

  8. 一起学微软Power BI系列-官方文档-入门指南(7)发布与共享-终结篇+完整PDF文档

    接触Power BI的时间也只有几个月,虽然花的时间不多,但通过各种渠道了解收集,谈不上精通,但对一些重要概念和细节还是有所了解.在整理官方文档的过程中,也熟悉和了解了很多概念.所以从前到后把微软官方 ...

  9. 全文检索引擎Solr系列——整合中文分词组件mmseg4j

    默认Solr提供的分词组件对中文的支持是不友好的,比如:“VIM比作是编辑器之神”这个句子在索引的的时候,选择FieldType为”text_general”作为分词依据时,分词效果是: 它把每一个词 ...

随机推荐

  1. 2014-11-9------- 设有一数据库,包括四个表:学生表(Student)、课程表(Course)、成绩表(Score)以及教师信息表(Teacher)。

    一.            设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...

  2. jQuery分析(1) - 介绍

    前言 web技术高速发展到现在已经出了现非常多的库或框架,库或框架实现方法也是五花八门.现在要实现一个web站点只需要根据自己的业务需求选择js框架即可快速完成.有些框架可以快速满足业务需求,但是有些 ...

  3. 测试functional的bind以及相关功能

    注:在VS2010 UPDATE1下测试通过 /*测试functional的bind以及相关功能*/ #include <iostream> #include <functional ...

  4. 安装ImageMagick扩展出现configure: error: not found. Please provide a path to MagickWand-config or Wand- config program

    安装ImageMagick扩展报错: checking ImageMagick MagickWand API configuration program... checking Testing /u ...

  5. Ext.String 方法

    1.Ext.String.htmlEncode(value); 编码字符串,对其中特殊字符进行转义 xt.String.htmlEncode("hello'world"); //& ...

  6. Hadoop, Python, and NoSQL lead the pack for big data jobs

    Hadoop, Python, and NoSQL lead the pack for big data jobs   Rise in cloud-based analytics could incr ...

  7. js实现中文转拼音

    首先需要注意ES6在严格模式下中常量太长会出问题,CHAR_DICT.FULL_DICT.POLYPHONE都是很大的常量,所以我都外部加载了,否则编译运行会有问题,先贴代码,常量在最后,如下: js ...

  8. matlab的二维卷积操作

    MATLAB的conv2函数实现步骤(conv2(A,B)): 其中,矩阵A和B的尺寸分别为ma*na即mb*nb ① 对矩阵A补零,第一行之前和最后一行之后都补mb-1行,第一列之前和最后一列之后都 ...

  9. php mysql PDO使用

    <?php $dbh = new PDO('mysql:host=localhost;dbname=access_control', 'root', ''); $dbh->setAttri ...

  10. 高性能页面加载技术(流水线加载)BigPipe的C#简单实现(附源码)

    一,BigPipe简介 BigPipe是一个重新设计的基础动态网页服务体系.大体思路是,分解网页成叫做Pagelets的小块,然后通过Web服务器和浏览器建立管道并管理他们在不同阶段的运行.这是类似于 ...