通过注解的方式来开发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();
    }

}


运行结果
Solr之基于注解开发-yellowcong_lucene

id问题

id是唯一的,如果id相同,就会认为这是一条数据,会将前面的数据更新掉。

#schema.xml 配置文件中,id是唯一的
<uniqueKey>id</uniqueKey>

#idstring类型的,这个必须注意,索引在Index的bean中, id也是string类型的,不然直接注入不进去
 <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />

Solr之基于注解开发-yellowcong_apache_02

环境搭建

项目结构

Solr之基于注解开发-yellowcong_solr_03

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