通过注解的方式来开发Solr,Solr中,提供了一个@Field注解,可以定义实体bean和索引的关系,然后直接添加实体Bean,进行数据查询,而不需要通过SolrInputDocument.addField 的方式进行数据的索引。需要重点注意的是1、实体类的id,必须是String类型的,在solr的schema.xml配置的2、注意schema.xml配置文件中,filed的multiValued字段配置
案例
Index的实体类
实体类的id,必须是String类型的,这是在solr的schema.xml已经配置过了
package com.yellowcong.index.entity;
import org.apache.solr.client.solrj.beans.Field;
public class Passage {
// 用于标明solr索引的id,需要放在字段上
@Field("id")
private String id;
@Field("content")
private String content;
@Field("username")
private String username;
@Field("title")
private String title;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
添加索引
/** * 添加两个实体Bean * @throws Exception * @throws SolrServerException */
public static void addIndex() throws Exception, SolrServerException {
// 建立SolrService
SolrServer server = new HttpSolrServer(SOLR_PATH);
Passage psg = new Passage();
psg.setContent("我是逗比,你是不是也是啊?");
psg.setId("1");
psg.setTitle("逗比生涯");
psg.setUsername("yellowcong");
Passage psg2 = new Passage();
psg2.setContent("我是中国人");
psg2.setId("2");
psg2.setTitle("中国人");
psg2.setUsername("yellowcong");
server.addBean(psg);
server.addBean(psg2);
// 提交
server.commit();
}
查询索引QueryResponse.getBeans
这种方式,是直接通过Bean来装索引查询来的数据
/** * 作者:yellowcong <br/> * 日期:2017/12/04 <br/> * 時間:15:32:56 <br/> * 描述:通过Bean对象来装数据 */
public static void queryByBean() throws Exception {
//查询数据
// 建立SolrService
SolrServer server = new HttpSolrServer(SOLR_PATH);
SolrQuery solrQuery = new SolrQuery();
solrQuery.add("q", "title:中");
//获取反悔数据
QueryResponse response = server.query(solrQuery);
//获取之
List<Passage> psgList = response.getBeans(Passage.class);
for(Passage psg:psgList) {
System.out.printf("%s:%s:%s",psg.getId(),psg.getTitle(),psg.getContent());
}
}
通过QueryResponse.query
/** * 作者:yellowcong <br/> * 日期:2017/12/04 <br/> * 時間:15:32:11 <br/> * 描述:通过QueryResponse.query 来获取数据 */
public static void queryByResult() throws Exception {
// 建立SolrService
SolrServer server = new HttpSolrServer(SOLR_PATH);
SolrQuery solrQuery = new SolrQuery();
solrQuery.add("q", "title:中");
//获取反悔数据
QueryResponse response = server.query(solrQuery);
//获取查询到的文档
SolrDocumentList docs = response.getResults();
System.out.println(docs.size());
for(SolrDocument doc: docs) {
String id = doc.get("id").toString();
String title = doc.get("title").toString();
String content = doc.get("content").toString();
String username = doc.get("username").toString();
System.out.printf("%s:%s:%s:%s",id,title,username,content);
}
}
完整代码
package day12_04;
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 com.yellowcong.index.entity.Passage;
/** * 作者:yellowcong <br/> * 日期:2017/12/04 <br/> * 時間:14:45:10 <br/> * 描述: */
public class Demo2 {
// solr的服务器地址
private static final String SOLR_PATH = "http://192.168.66.100:8080/solr/";
public static void main(String[] args) throws Exception {
//添加索引
addIndex();
//查询结果,通过QueryResponse.query
System.out.println("---------------QueryResponse.query方法-----------------");
queryByResult();
//实际开发通过标注的方式比较的多
//通过Bean 对象来装数据
System.out.println("---------------QueryResponse.getBeans方法-----------------");
queryByBean();
}
/** * 作者:yellowcong <br/> * 日期:2017/12/04 <br/> * 時間:15:32:56 <br/> * 描述:通过Bean对象来装数据 */
public static void queryByBean() throws Exception {
//查询数据
// 建立SolrService
SolrServer server = new HttpSolrServer(SOLR_PATH);
SolrQuery solrQuery = new SolrQuery();
solrQuery.add("q", "title:中");
//获取反悔数据
QueryResponse response = server.query(solrQuery);
//获取之
List<Passage> psgList = response.getBeans(Passage.class);
for(Passage psg:psgList) {
System.out.printf("%s:%s:%s",psg.getId(),psg.getTitle(),psg.getContent());
}
}
/** * 作者:yellowcong <br/> * 日期:2017/12/04 <br/> * 時間:15:32:11 <br/> * 描述:通过QueryResponse.query 来获取数据 */
public static void queryByResult() throws Exception {
// 建立SolrService
SolrServer server = new HttpSolrServer(SOLR_PATH);
SolrQuery solrQuery = new SolrQuery();
solrQuery.add("q", "title:中");
//获取反悔数据
QueryResponse response = server.query(solrQuery);
//获取查询到的文档
SolrDocumentList docs = response.getResults();
System.out.println(docs.size());
for(SolrDocument doc: docs) {
String id = doc.get("id").toString();
String title = doc.get("title").toString();
String content = doc.get("content").toString();
String username = doc.get("username").toString();
System.out.printf("%s:%s:%s:%s",id,title,username,content);
}
}
/** * 添加两个实体Bean * @throws Exception * @throws SolrServerException */
public static void addIndex() throws Exception, SolrServerException {
// 建立SolrService
SolrServer server = new HttpSolrServer(SOLR_PATH);
Passage psg = new Passage();
psg.setContent("我是逗比,你是不是也是啊?");
psg.setId("1");
psg.setTitle("逗比生涯");
psg.setUsername("yellowcong");
Passage psg2 = new Passage();
psg2.setContent("我是中国人");
psg2.setId("2");
psg2.setTitle("中国人");
psg2.setUsername("yellowcong");
server.addBean(psg);
server.addBean(psg2);
// 提交
server.commit();
}
}
运行结果
id问题
id是唯一的,如果id相同,就会认为这是一条数据,会将前面的数据更新掉。
#schema.xml 配置文件中,id是唯一的
<uniqueKey>id</uniqueKey>
#id是string类型的,这个必须注意,索引在Index的bean中, id也是string类型的,不然直接注入不进去
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
环境搭建
项目结构
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>yellowcong</groupId>
<artifactId>day12_04</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>day12_04</name>
<url>http://maven.apache.org</url>
<!-- 配置国内比较快的 阿里云的Maven仓库 -->
<repositories>
<repository>
<id>aliyunmaven</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<lucene.version>4.5.1</lucene.version>
<mmseg4j.version>1.9.1</mmseg4j.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!-- lucene核心包 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>${lucene.version}</version>
</dependency>
<!--QueryParser 查询类 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>${lucene.version}</version>
</dependency>
<!-- 分词器 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>${lucene.version}</version>
</dependency>
<!-- 高亮显示 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>${lucene.version}</version>
</dependency>
<!-- 庖丁解牛分词器 -->
<dependency>
<groupId>com.chenlb.mmseg4j</groupId>
<artifactId>mmseg4j-core</artifactId>
<version>${mmseg4j.version}</version>
</dependency>
<dependency>
<groupId>com.chenlb.mmseg4j</groupId>
<artifactId>mmseg4j-analysis</artifactId>
<version>${mmseg4j.version}</version>
</dependency>
<!-- ikanalyzer 分词器 -->
<dependency>
<groupId>com.janeluo</groupId>
<artifactId>ikanalyzer</artifactId>
<version>2012_u6</version>
</dependency>
<!-- solrj -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>4.5.1</version>
</dependency>
<!-- 日志配置文件,必须有,不然会报错 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.16</version>
</dependency>
</dependencies>
</project>
log4j.xml
#log4j.rootLogger=debug,Console
log4j.rootLogger=error,Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c]%m%n
错误合集
Invalid setter method
对于Solr索引的实体bean,需要将@Field
标注放在字段上面,而不是方法上面,下面是一个例子
Exception in thread "main" org.apache.solr.client.solrj.beans.BindingException: Invalid setter method. Must have one and only one parameter
at org.apache.solr.client.solrj.beans.DocumentObjectBinder$DocField.storeType(DocumentObjectBinder.java:202)
at org.apache.solr.client.solrj.beans.DocumentObjectBinder$DocField.<init>(DocumentObjectBinder.java:150)
at org.apache.solr.client.solrj.beans.DocumentObjectBinder.collectInfo(DocumentObjectBinder.java:119)
at org.apache.solr.client.solrj.beans.DocumentObjectBinder.getDocFields(DocumentObjectBinder.java:99)
at org.apache.solr.client.solrj.beans.DocumentObjectBinder.toSolrInputDocument(DocumentObjectBinder.java:73)
at org.apache.solr.client.solrj.SolrServer.addBean(SolrServer.java:136)
at org.apache.solr.client.solrj.SolrServer.addBean(SolrServer.java:125)
at day12_04.Demo2.main(Demo2.java:31)
solr的实体类,所以的字段标注,都是在Field字段上
public class Passage {
// 用于标明solr索引的id,需要放在字段上
@Field("id")
private int id;
@Field("content")
private String content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
unknown field
这是由于schema.xml 配置文件,里面没有username这个字段所导致的。
Exception in thread "main" org.apache.solr.client.solrj.impl.HttpSolrServer$RemoteSolrException: ERROR: [doc=2] unknown field 'username'
at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:425)
at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:180)
at org.apache.solr.client.solrj.request.AbstractUpdateRequest.process(AbstractUpdateRequest.java:117)
at org.apache.solr.client.solrj.SolrServer.add(SolrServer.java:116)
at org.apache.solr.client.solrj.SolrServer.addBean(SolrServer.java:136)
at org.apache.solr.client.solrj.SolrServer.addBean(SolrServer.java:125)
at day12_04.Demo2.main(Demo2.java:38)
修改配置文件
#修改schema.xml 配置文件
vim /usr/local/solr/solr-4.10.3/example/solr/collection1/conf/schema.xml
#添加字段,
#name 表示索引的字段
#type 表示用那个分词器
#indexed 是否索引
#stored 是否存储(对于文章内容,不要 stored)
#multiValued 表示的是否是多个数据,数组类型的数据(这个一定要修改,不然就导致document 变成Bean 有问题)
<field name="title" type="text_general" indexed="true" stored="true" multiValued="false"/>
<field name="username" type="text_general" indexed="true" stored="true" multiValued="false"/>
<field name="content" type="text_general" indexed="false" stored="true" multiValued="false"/>
#重启tomcat
#关闭tomcat
/usr/local/solr/apache-tomcat-7.0.62/bin/shutdown.sh
#启动tomcat
/usr/local/solr/apache-tomcat-7.0.62/bin/startup.sh
Solr实例化对象时,报错提示无法实例化对象。
解决方案是:实体类的类访问级别应该是public 的。,我刚开始是把他弄在一个类里面的,后来导致获取不到了,需要设置为public的
Caused by: java.lang.IllegalAccessException: Class org.apache.solr.client.solrj.beans.DocumentObjectBinder can not access a member of class day12_04.Demo2$Passage with modifiers ""
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.Class.newInstance(Class.java:436)
at org.apache.solr.client.solrj.beans.DocumentObjectBinder.getBean(DocumentObjectBinder.java:62)
... 4 more
id问题( Can not set int field)
id这个字段,必须是string类型的,因为在solr的schema.xml 配置中,设定id是string类型
Caused by: java.lang.IllegalArgumentException: Can not set int field com.yellowcong.index.entity.Passage.id to java.lang.String
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeIntegerFieldAccessorImpl.set(UnsafeIntegerFieldAccessorImpl.java:98)
at java.lang.reflect.Field.set(Field.java:764)
at org.apache.solr.client.solrj.beans.DocumentObjectBinder$DocField.set(DocumentObjectBinder.java:364)
... 6 more