侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 292 篇文章
  • 累计创建 132 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

SpringBoot整合solr及基本操作介绍

孔子说JAVA
2022-08-27 / 0 评论 / 0 点赞 / 50 阅读 / 20,744 字 / 正在检测是否收录...

solr服务器搭建起来后, 如果想要使数据加入到Solr服务器中,则在schema.xml中必须要存在与其对应的 Filed 标签声明,当我们添加一个对象时,可以一个一个的setFiled,当Filed较多的时候操作比较麻烦,Solr允许使用javaBean的方式将一个对象直接保存到solr服务器中。solrj 是 solr 的java客户端,用于访问solr索引库。它提供了添加、删除、查询、优化等功能。

image-1661506052847

1、定义 Schema 信息

假设我们需要操作一个描述诗人信息的文档,首先在schema.xml中定义Poet(诗人)对象的具体字段,字段说明如下:

字段 描述
id 唯一主键
age 年龄
name 姓名
poems 诗歌
about 简介
success 成就

定义的 schema 信息如下:

<field name="about" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
<field name="age" type="pint" uninvertible="true" indexed="true" stored="true"/>
<field name="content" type="text_ik" uninvertible="true" indexed="true" stored="true" multiValued="true"/>
<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
<field name="name" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
<field name="poems" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
<field name="success" type="text_ik" uninvertible="true" indexed="true" stored="true"/>

2、springboot整合solr

2.1 引入依赖

solrj是solr的java客户端,用于访问solr索引库。它提供了添加、删除、查询、优化等功能。

springboot引入依赖方式1:

<properties>
    <spring.data.solr.version>2.1.1.RELEASE</spring.data.solr.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-solr</artifactId>
            <version>${spring.data.solr.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>  
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-solr</artifactId>
    </dependency>

    <!-- 默认 starter 会加载 solrj 进来, 下面这个可以不引-->
    <dependency>
        <groupId>org.apache.solr</groupId>
        <artifactId>solr-solrj</artifactId>
        <version>8.9.0</version>
    </dependency>
</dependencies>

springboot引入依赖方式2:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>

普通java项目引入依赖的方式:

<dependency>
    <groupId>org.apache.solr</groupId>
    <artifactId>solr-solrj</artifactId>
    <version>8.9.0</version>
</dependency>
<dependency>
    <groupId>org.apache.solr</groupId>
    <artifactId>solr-core</artifactId>
    <version>8.9.0</version>
</dependency>

2.2 配置文件

server:
  context-path: /
  port: 8080
spring:
  data:
    solr:
      # 这里的core就是索引核心库的名称,这里也可以不用写core,这时候就需要在代码中使用的时候去指定core,如果是集群,这里的core填写的是collection名称。
      # host: http://127.0.0.1:8983/solr 或 http://127.0.0.1:8983/solr/core
      host: http://127.0.0.1:8983/solr/core

solr 的 host 可以写成http://127.0.0.1:8983/solr 或 http://127.0.0.1:8983/solr/core ,这里的core就是索引核心库的名称,如果连接的是solr集群,core为需要连接的 collection 名称。(core或collection可以理解为数据库的概念)

2.3 编写实体类

在java中建立实体对象,并且一定要在属性或set方法上添加@Field(nameValue)注解。(org.apache.solr.client.solrj.beans.Field)

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

public class PoetInfo {
    @Field
    private String id;

    @Field
    private Integer age;

    @Field
    private String name;

    @Field
    private String poems;

    @Field
    private String about;

    @Field
    private String success;

    public PoetInfo() {
    }

    public PoetInfo(String id, Integer age, String name, String poems, String about, String success) {
        this.id = id;
        this.age = age;
        this.name = name;
        this.poems = poems;
        this.about = about;
        this.success = success;
    }

    @Override
    public String toString() {
        return "Info{" +
                "id='" + id + '\'' +
                ", age=" + age +
                ", name='" + name + '\'' +
                ", poems='" + poems + '\'' +
                ", about='" + about + '\'' +
                ", success='" + success + '\'' +
                '}';
    }

    // getter、setter方法
}

2.4 solr基本操作类

旧版本的连接服务 HttpSolrServer 在solr5版本后已经停用,被新的 HttpSolrClient 取代,具体用法如下。

HttpSolrClient server=new HttpSolrClient(url);
//设置对应请求的目标主机线程数为1000条
server.setDefaultMaxConnectionsPerHost(1000); server.setMaxTotalConnections(10000);
server.setConnectionTimeout(60000);//设置连接超时时间(单位毫秒) 1000
server.setSoTimeout(60000);//// 设置读数据超时时间(单位毫秒) 1000
server.setFollowRedirects(false);//遵循从定向
server.setAllowCompression(true);//允许压缩

上述代码在普通java项目中可以使用,在springboot中可以直接注入 SolrClient 来使用。下面的 SolrDao.java 实现索引的增删改查功能。

2.4.1 增加/更新文档

通过SolrInputDocument 的 添加动态索引属性(增加/更新文档)

    /**
     * 添加动态索引属性(增加/更新文档)
     *
     * @param coreName 索引核心库
     * @throws SolrServerException
     * @throws IOException
     */
    public void addIndex(String coreName) throws SolrServerException, IOException {
        SolrInputDocument document = new SolrInputDocument();
        // 默认情况下必须添加的字段,用来区分文档的唯一标识
        document.addField("id", "1");
        document.addField("age", 30);
        document.addField("name", "李白");
        document.addField("poems", "望庐山瀑布");
        document.addField("about", "字太白");
        document.addField("success", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");

        SolrInputDocument document2 = new SolrInputDocument();
        document2.addField("id", "2");
        document2.addField("age", 31);
        document2.addField("name", "杜甫");
        document2.addField("poems", "望岳");
        document2.addField("about", "字子美");
        document2.addField("success", "唐代伟大的现实主义文学作家,唐诗思想艺术的集大成者");
        /*
         * 如果spring.data.solr.host 里面配置到 core了, 这里就不需要传 coreName 这个参数了
         */
        solrClient.add(coreName, document);
        solrClient.add(coreName, document2);
        solrClient.commit(coreName, true,true);
    }

通过实体类来添加动态索引属性(增加/更新文档)

    /**
     * 通过实体类来添加动态索引属性(增加/更新文档)
     *
     * @param coreName 索引核心库
     * @throws SolrServerException
     * @throws IOException
     */
    public void addIndexByBean(String coreName) throws SolrServerException, IOException {
        PoetInfo info = new PoetInfo("1", 40, "李白", "望庐山瀑布", "字太白", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
        solrClient.addBean(coreName, info);
        solrClient.commit(coreName, true,true);
    }

2.4.2 查询文档

通过 MapSolrParams 查询

    /**
     * 通过 MapSolrParams 查询
     *
     * @param coreName 索引核心库
     * @throws IOException
     * @throws SolrServerException
     */
    public void query(String coreName) throws IOException, SolrServerException {
        Map<String, String> map = new HashMap<>();
        //查询条件
        map.put("q", "*:*");
        //要显示的内容
        map.put("fl", "id,age,name,poems");
        //排序方式
        map.put("sort", "id asc");
        MapSolrParams solrParams = new MapSolrParams(map);

        QueryResponse queryResponse = solrClient.query(coreName, solrParams);
        SolrDocumentList documents = queryResponse.getResults();
        logger.info("查询到{}个文档!", documents.getNumFound());
        for (SolrDocument document : documents) {
            String id = (String)document.getFieldValue("id");
            Integer age = (Integer)document.getFieldValue("age");
            String name = (String)document.getFieldValue("name");
            String poems = (String)document.getFieldValue("poems");
            logger.info("id={},age={},name={},poems={}", id, age, name, poems);
        }
    }

通过 solrQuery 查询

    /**
     * 通过 solrQuery 查询
     *
     * @param coreName 索引核心库
     * @throws IOException
     * @throws SolrServerException
     */
    public void solrQuery(String coreName) throws IOException, SolrServerException {
        SolrQuery solrQuery = new SolrQuery("*:*");
        solrQuery.addField("id");
        solrQuery.addField("age");
        solrQuery.addField("name");
        solrQuery.addField("poems");
        solrQuery.addSort("id", SolrQuery.ORDER.asc);
        //设置返回的行数
        solrQuery.setRows(10);

        QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
        SolrDocumentList documents = queryResponse.getResults();
        logger.info("查询到{}个文档!", documents.getNumFound());
        for (SolrDocument document : documents) {
            String id = (String)document.getFieldValue("id");
            Integer age = (Integer)document.getFieldValue("age");
            String name = (String)document.getFieldValue("name");
            String poems = (String)document.getFieldValue("poems");
            logger.info("id={},age={},name={},poems={}", id, age, name, poems);
        }
    }

查询返回实例类对象

    /**
     * 查询返回实例类对象
     *
     * @param coreName 索引核心库
     * @throws IOException
     * @throws SolrServerException
     */
    public void solrQueryBean(String coreName) throws IOException, SolrServerException {
        SolrQuery solrQuery = new SolrQuery("*:*");
        solrQuery.addField("id");
        solrQuery.addField("age");
        solrQuery.addField("name");
        solrQuery.addField("poems");
        solrQuery.addField("about");
        solrQuery.addField("success");
        solrQuery.addSort("id", SolrQuery.ORDER.asc);
        //设置返回的行数
        solrQuery.setRows(10);

        QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
        List<PoetInfo> list = queryResponse.getBeans(PoetInfo.class);
        logger.info("查询到{}个文档!", list.size());
        for (PoetInfo info : list) {
            logger.info(info.toString());
        }
    }

2.4.3 删除文档

根据id删除文档(索引)

    /**
     * 根据id删除索引
     *
     * @param coreName 索引核心库
     * @param id
     * @throws SolrServerException
     * @throws IOException
     */
    public void delIndex(String coreName, String id) throws SolrServerException, IOException {
        solrClient.deleteById(coreName, id);
        solrClient.commit(coreName, true,true);
    }

根据名称删除文档(索引)

    /**
     * 根据名称删除索引
     *
     * @param coreName 索引核心库
     * @param name 诗人姓名
     * @throws SolrServerException
     * @throws IOException
     */
    public void delIndexByName(String coreName, String name) throws IOException, SolrServerException {
//        solrClient.deleteByQuery(coreName, "name:杜甫");
        solrClient.deleteByQuery(coreName, "name:"+name);
        solrClient.commit(coreName, true,true);
    }

2.4.4 完整代码

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
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 org.apache.solr.common.params.MapSolrParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 使用solrJ 向solr 提交请求,增删改查, solrJ 底层页是发送 http 协议
 */
@Component
public class SolrDAO {
    private static Logger logger = LoggerFactory.getLogger(SolrDAO.class);
    @Autowired
    private SolrClient solrClient;

    /**
     * 添加动态索引属性(增加/更新文档)
     *
     * @param coreName 索引核心库
     * @throws SolrServerException
     * @throws IOException
     */
    public void addIndex(String coreName) throws SolrServerException, IOException {
        SolrInputDocument document = new SolrInputDocument();
        // 默认情况下必须添加的字段,用来区分文档的唯一标识
        document.addField("id", "1");
        document.addField("age", 30);
        document.addField("name", "李白");
        document.addField("poems", "望庐山瀑布");
        document.addField("about", "字太白");
        document.addField("success", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");

        SolrInputDocument document2 = new SolrInputDocument();
        document2.addField("id", "2");
        document2.addField("age", 31);
        document2.addField("name", "杜甫");
        document2.addField("poems", "望岳");
        document2.addField("about", "字子美");
        document2.addField("success", "唐代伟大的现实主义文学作家,唐诗思想艺术的集大成者");
        /*
         * 如果spring.data.solr.host 里面配置到 core了, 这里就不需要传 coreName 这个参数了
         */
        solrClient.add(coreName, document);
        solrClient.add(coreName, document2);
        solrClient.commit(coreName, true,true);
    }

    /**
     * 通过实体类来添加动态索引属性(增加/更新文档)
     *
     * @param coreName 索引核心库
     * @throws SolrServerException
     * @throws IOException
     */
    public void addIndexByBean(String coreName) throws SolrServerException, IOException {
        PoetInfo info = new PoetInfo("1", 40, "李白", "望庐山瀑布", "字太白", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
        solrClient.addBean(coreName, info);
        solrClient.commit(coreName, true,true);
    }

    /**
     * 根据id删除索引
     *
     * @param coreName 索引核心库
     * @param id
     * @throws SolrServerException
     * @throws IOException
     */
    public void delIndex(String coreName, String id) throws SolrServerException, IOException {
        solrClient.deleteById(coreName, id);
        solrClient.commit(coreName, true,true);
    }

    /**
     * 根据名称删除索引
     *
     * @param coreName 索引核心库
     * @param name 诗人姓名
     * @throws SolrServerException
     * @throws IOException
     */
    public void delIndexByName(String coreName, String name) throws IOException, SolrServerException {
//        solrClient.deleteByQuery(coreName, "name:杜甫");
        solrClient.deleteByQuery(coreName, "name:"+name);
        solrClient.commit(coreName, true,true);
    }

    /**
     * 通过 MapSolrParams 查询
     *
     * @param coreName 索引核心库
     * @throws IOException
     * @throws SolrServerException
     */
    public void query(String coreName) throws IOException, SolrServerException {
        Map<String, String> map = new HashMap<>();
        //查询条件
        map.put("q", "*:*");
        //要显示的内容
        map.put("fl", "id,age,name,poems");
        //排序方式
        map.put("sort", "id asc");
        MapSolrParams solrParams = new MapSolrParams(map);

        QueryResponse queryResponse = solrClient.query(coreName, solrParams);
        SolrDocumentList documents = queryResponse.getResults();
        logger.info("查询到{}个文档!", documents.getNumFound());
        for (SolrDocument document : documents) {
            String id = (String)document.getFieldValue("id");
            Integer age = (Integer)document.getFieldValue("age");
            String name = (String)document.getFieldValue("name");
            String poems = (String)document.getFieldValue("poems");
            logger.info("id={},age={},name={},poems={}", id, age, name, poems);
        }
    }

    /**
     * 通过 solrQuery 查询
     *
     * @param coreName 索引核心库
     * @throws IOException
     * @throws SolrServerException
     */
    public void solrQuery(String coreName) throws IOException, SolrServerException {
        SolrQuery solrQuery = new SolrQuery("*:*");
        solrQuery.addField("id");
        solrQuery.addField("age");
        solrQuery.addField("name");
        solrQuery.addField("poems");
        solrQuery.addSort("id", SolrQuery.ORDER.asc);
        //设置返回的行数
        solrQuery.setRows(10);

        QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
        SolrDocumentList documents = queryResponse.getResults();
        logger.info("查询到{}个文档!", documents.getNumFound());
        for (SolrDocument document : documents) {
            String id = (String)document.getFieldValue("id");
            Integer age = (Integer)document.getFieldValue("age");
            String name = (String)document.getFieldValue("name");
            String poems = (String)document.getFieldValue("poems");
            logger.info("id={},age={},name={},poems={}", id, age, name, poems);
        }
    }

    /**
     * 查询返回实例类对象
     *
     * @param coreName 索引核心库
     * @throws IOException
     * @throws SolrServerException
     */
    public void solrQueryBean(String coreName) throws IOException, SolrServerException {
        SolrQuery solrQuery = new SolrQuery("*:*");
        solrQuery.addField("id");
        solrQuery.addField("age");
        solrQuery.addField("name");
        solrQuery.addField("poems");
        solrQuery.addField("about");
        solrQuery.addField("success");
        solrQuery.addSort("id", SolrQuery.ORDER.asc);
        //设置返回的行数
        solrQuery.setRows(10);

        QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
        List<PoetInfo> list = queryResponse.getBeans(PoetInfo.class);
        logger.info("查询到{}个文档!", list.size());
        for (PoetInfo info : list) {
            logger.info(info.toString());
        }
    }
}

3、其他

HttpSolrClient的方式。

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
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 org.apache.solr.common.params.MapSolrParams;
import org.junit.After;
import org.junit.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 使用solrJ 向solr 提交请求,增删改查, solrJ 底层页是发送 http 协议
 */
@Component
public class SolrDAO {
    private static Logger logger = LoggerFactory.getLogger(SolrDAO.class);

    private HttpSolrClient solrClient;

    @Before
    public void before() {
        solrClient = new HttpSolrClient.Builder("http://10.40.100.69:8983/solr")
                .withConnectionTimeout(10000)
                .withSocketTimeout(60000)
                .build();
    }

    @After
    public void after() throws IOException {
        solrClient.close();
    }

    /**
     * 添加动态索引属性(增加/更新文档)
     *
     * @param coreName 索引核心库
     * @throws SolrServerException
     * @throws IOException
     */
    public void addIndex(String coreName) throws SolrServerException, IOException {
        SolrInputDocument document = new SolrInputDocument();
        // 默认情况下必须添加的字段,用来区分文档的唯一标识
        document.addField("id", "1");
        document.addField("age", 30);
        document.addField("name", "李白");
        document.addField("poems", "望庐山瀑布");
        document.addField("about", "字太白");
        document.addField("success", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");

        SolrInputDocument document2 = new SolrInputDocument();
        document2.addField("id", "2");
        document2.addField("age", 31);
        document2.addField("name", "杜甫");
        document2.addField("poems", "望岳");
        document2.addField("about", "字子美");
        document2.addField("success", "唐代伟大的现实主义文学作家,唐诗思想艺术的集大成者");
        /*
         * 如果spring.data.solr.host 里面配置到 core了, 这里就不需要传 coreName 这个参数了
         */
        solrClient.add(coreName, document);
        solrClient.add(coreName, document2);
        solrClient.commit(coreName, true,true);
    }

    /**
     * 通过实体类来添加动态索引属性(增加/更新文档)
     *
     * @param coreName 索引核心库
     * @throws SolrServerException
     * @throws IOException
     */
    public void addIndexByBean(String coreName) throws SolrServerException, IOException {
        PoetInfo info = new PoetInfo("1", 40, "李白", "望庐山瀑布", "字太白", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
        solrClient.addBean(coreName, info);
        solrClient.commit(coreName, true,true);
    }

    /**
     * 根据id删除索引
     *
     * @param coreName 索引核心库
     * @param id
     * @throws SolrServerException
     * @throws IOException
     */
    public void delIndex(String coreName, String id) throws SolrServerException, IOException {
        solrClient.deleteById(coreName, id);
        solrClient.commit(coreName, true,true);
    }

    /**
     * 根据名称删除索引
     *
     * @param coreName 索引核心库
     * @param name 诗人姓名
     * @throws SolrServerException
     * @throws IOException
     */
    public void delIndexByName(String coreName, String name) throws IOException, SolrServerException {
//        solrClient.deleteByQuery(coreName, "name:杜甫");
        solrClient.deleteByQuery(coreName, "name:"+name);
        solrClient.commit(coreName, true,true);
    }

    /**
     * 通过 MapSolrParams 查询
     *
     * @param coreName 索引核心库
     * @throws IOException
     * @throws SolrServerException
     */
    public void query(String coreName) throws IOException, SolrServerException {
        Map<String, String> map = new HashMap<>();
        //查询条件
        map.put("q", "*:*");
        //要显示的内容
        map.put("fl", "id,age,name,poems");
        //排序方式
        map.put("sort", "id asc");
        MapSolrParams solrParams = new MapSolrParams(map);

        QueryResponse queryResponse = solrClient.query(coreName, solrParams);
        SolrDocumentList documents = queryResponse.getResults();
        logger.info("查询到{}个文档!", documents.getNumFound());
        for (SolrDocument document : documents) {
            String id = (String)document.getFieldValue("id");
            Integer age = (Integer)document.getFieldValue("age");
            String name = (String)document.getFieldValue("name");
            String poems = (String)document.getFieldValue("poems");
            logger.info("id={},age={},name={},poems={}", id, age, name, poems);
        }
    }

    /**
     * 通过 solrQuery 查询
     *
     * @param coreName 索引核心库
     * @throws IOException
     * @throws SolrServerException
     */
    public void solrQuery(String coreName) throws IOException, SolrServerException {
        SolrQuery solrQuery = new SolrQuery("*:*");
        solrQuery.addField("id");
        solrQuery.addField("age");
        solrQuery.addField("name");
        solrQuery.addField("poems");
        solrQuery.addSort("id", SolrQuery.ORDER.asc);
        //设置返回的行数
        solrQuery.setRows(10);

        QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
        SolrDocumentList documents = queryResponse.getResults();
        logger.info("查询到{}个文档!", documents.getNumFound());
        for (SolrDocument document : documents) {
            String id = (String)document.getFieldValue("id");
            Integer age = (Integer)document.getFieldValue("age");
            String name = (String)document.getFieldValue("name");
            String poems = (String)document.getFieldValue("poems");
            logger.info("id={},age={},name={},poems={}", id, age, name, poems);
        }
    }

    /**
     * 查询返回实例类对象
     *
     * @param coreName 索引核心库
     * @throws IOException
     * @throws SolrServerException
     */
    public void solrQueryBean(String coreName) throws IOException, SolrServerException {
        SolrQuery solrQuery = new SolrQuery("*:*");
        solrQuery.addField("id");
        solrQuery.addField("age");
        solrQuery.addField("name");
        solrQuery.addField("poems");
        solrQuery.addField("about");
        solrQuery.addField("success");
        solrQuery.addSort("id", SolrQuery.ORDER.asc);
        //设置返回的行数
        solrQuery.setRows(10);

        QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
        List<PoetInfo> list = queryResponse.getBeans(PoetInfo.class);
        logger.info("查询到{}个文档!", list.size());
        for (PoetInfo info : list) {
            logger.info(info.toString());
        }
    }
}
0

评论区