Solr之基於註解開發-yellowcong
阿新 • • 發佈:2019-02-16
通過註解的方式來開發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