Solr环境搭建、java调用服务以及数据同步

本文记录第一次使用全文搜索引擎Solr,主要介绍Solr环境搭建,数据查询及数据同步,不当之处请指教。此说明使用solr8.7.0版本。

  1. 下载地址:https://solr.apache.org/downloads.html

2. 解压后目录结构如下
solr目录结构
3. doc命令进入solr下bin目录,输入solr start命令启动服务,默认端口是8983,表示启动成功,浏览器输入http://127.0.0.1:8983/solr可以访问表示启动成功。
在这里插入图片描述
在这里插入图片描述
4. 创建core,doc窗口输入命令solr create -c [core名称],查看solr-8.7.0\server\solr目录下会出现与core名称相同文件夹表示创建成功(也可以使用web端创建,但是创建时失败,建议使用命令创建)
在这里插入图片描述
在这里插入图片描述
5. 配置core
5.1创建dataConfig.xml配置文件,配置数据库地址,以及entity,query定义sql满足检索查询需要,多个表数据可以使用UNION连接

<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>  
  <dataSource
        driver="com.mysql.jdbc.Driver"
        url="jdbc:mysql://172.0.0.1:3306/test"
        user="renzhx" password="123456"
		batchSize="-1"/>
  <document>
	  <entity name="search" pk="2" query="SELECT CONCAT(news_id,'-','news') id,news_title entry_body,'news' entry_typ FROM web_news" >
        <field column="id" name="id"/>
        <field column="entry_body" name="entryBody"/>
		<field column="entry_typ" name="entryType"/>
      </entity>
  </document>
</dataConfig>

5.2在managed-schema中配置dataConfig.xml中的field以及分词器,本文使用ik_work分词器
在这里插入图片描述

<field name="entryBody" type="ik_word" indexed="true" stored="true"/>
	<field name="entryType" type="string"/>
	<field name="entryTime" type="string"/>
	
	<fieldType name="ik_word" class="solr.TextField">
		<analyzer type="index">
			<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
			<filter class="solr.LowerCaseFilterFactory"/>
		</analyzer>
		<analyzer type="query">
			<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
			<filter class="solr.LowerCaseFilterFactory"/>
		</analyzer>
	</fieldType>

5.3 完成上述操作后命令重启solr即可,solr stop,solr start
5.4使用solr web管理页面导入数据,选中创建Core,进入Core压面后选中DataImport按照下图所示进行数据导入。
在这里插入图片描述
在这里插入图片描述
5.5验证数据导入是否成功,选中query,直接选中Execute Query进行查询,数据即可展示出来,配置完成。
在这里插入图片描述

6. Java调用服务,直接上代码
pom文件引入依赖

<!--solr全文检索-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>

application.yml

spring:
	data:
	    solr:
	      host: http://127.0.0.1:8983/solr

6.1创建实体类

@SolrDocument(solrCoreName = "search")
public class SolrEntry {

    @Id
    @Field
    private String id;

    @Field
    private String entryBody;

    @Field
    private String entryType;

    @Field
    public String entryTime;
}

6.2 实现查询、新增,修改、删除功能

@Service
public class SolrServiceImpl implements SolrService {

    @Autowired
    private SolrClient solrClient;

    @Autowired
    private WebHotSearchMapper hotSearchMapper;

    /**
     * 查询数据
     * @param param
     * @return
     */
    @Override
    public QueryResponse search(Map<String, Object> param) {
        QueryResponse queryResponse = null;
        Integer pageNum = (Integer)param.get("pageNum");
        if(pageNum == null)pageNum = 0;
        Integer pageSize = (Integer)param.get("pageSize");
        if(pageSize == null) pageSize = 10;
        String coreName = (String)param.get("coreName");
        if(coreName == null){
            return null;
        }
        String keyWord = (String)param.get("keyWord");
        SolrQuery where = new SolrQuery();
        // 设置分页
        where.setStart(pageNum - 1);
        where.setRows(pageSize);
        // 设置关键词
        if("".equals(keyWord)||keyWord == null){
            keyWord = "*";
        }
        where.setQuery("entryBody:" + keyWord);
        // 添加过滤器
        String entryType = (String)param.get("entryType");
        if(entryType != null&& entryType != ""){
            where.setFilterQueries("entryType:" + entryType);
        }
        where.setSort("entryTime", SolrQuery.ORDER.desc);
        WebHotSearch hotSearch = new WebHotSearch();
        try {
            queryResponse = solrClient.query(coreName,where);
            hotSearch.setHotWord(keyWord);
            hotSearch.setCreateTime(DateUtils.getNowDate());
            hotSearch.setCreateBy(SecurityUtils.getUsername());
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (CustomException e){
            hotSearch.setCreateBy("游客");
        }
        hotSearchMapper.insertWebHotSearch(hotSearch);
        return queryResponse;
    }

    /**
     * solr同步-新增或修改
     * @param solrEntry
     * @param coreName
     * @return
     */
    @Override
    public String insertOrUpdate(SolrEntry solrEntry,String coreName) {
        SolrInputDocument in = new SolrInputDocument();
        in.setField("id",solrEntry.getId());
        in.setField("entryBody",solrEntry.getEntryBody());
        in.setField("entryType",solrEntry.getEntryType());
        try {
            solrClient.add(coreName,in);
            solrClient.commit(coreName);
            return solrEntry.getId();
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "-1";
    }

    /**
     * solr数据同步-删除
     * @param solrEntry
     * @param coreName
     * @return
     */
    @Override
    public String delete(SolrEntry solrEntry,String coreName) {
        String id = solrEntry.getId() + "-" + solrEntry.getEntryType();
        try {
            solrClient.deleteById(coreName,id);
            solrClient.commit(coreName);
            return id;
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "-1";
    }
}

6.3数据同步使用注解实现。

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SolrKey {
    public String value() default "ID";
}
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SolrSynchro {

    // 类型,区分solr数据来源
    public String type() default "";

    // solr核心名称
    public String coreName() default "";

    // 同步方法 INSERT UPDATE DELETE
    public String method() default "";
}

@Aspect
@Component
public class SolrSynchroAspect {

    @Autowired
    private SolrService solrService;

    @Pointcut("@annotation(com.tydt.framework.aspectj.lang.annotation.SolrSynchro)")
    public void solrSynchroPointCut(){

    }

    @AfterReturning("solrSynchroPointCut()")
    public void doAfterReturning(JoinPoint joinPoint){
        // 获取第一个参数
        Object arg = joinPoint.getArgs()[0];
        // 获取类所有属性
        Field[] fields = arg.getClass().getDeclaredFields();
        SolrEntry solrEntry = new SolrEntry();
        SolrSynchro solrSynchro = getSolrSynchro(joinPoint);
        String type = solrSynchro.type();
        String coreName = solrSynchro.coreName();
        solrEntry.setEntryType(type);
        try{
            for (Field field : fields) {
                // 判断属性是否被指定注解
                boolean present = field.isAnnotationPresent(SolrKey.class);
                if(present){
                    // 获取字段注解value
                    SolrKey solrKey = field.getAnnotation(SolrKey.class);
                    String keyValue = solrKey.value();
                    // 获取字段名称
                    String fieldName = field.getName();
                    // 首字母大写
                    fieldName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                    // 获取getter方法
                    Method method = arg.getClass().getMethod("get" + fieldName);
                    // 执行getter方法获取值
                    if("ID".equals(keyValue)){// solr ID字段
                        Long solrValue = Long.parseLong(method.invoke(arg).toString()) ;
                        // ID
                        solrEntry.setId(solrValue + "-" + type);
                    }else if("BODY".equals(keyValue)){// solr 检索词条内容
                        String solrValue = (String) method.invoke(arg);
                        solrEntry.setEntryBody(solrValue);
                    }
                }
            }
            // 判断更新、删除、添加
            switch (solrSynchro.method()){
                case "INSERT":
                case "UPDATE":
                    solrService.insertOrUpdate(solrEntry,coreName);
                    break;
                case "DELETE":
                    solrService.delete(solrEntry,coreName);
                    break;
            }
        }catch (NoSuchMethodException e){
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取需要同步的方法
     */
    public SolrSynchro getSolrSynchro(JoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        SolrSynchro solrSynchro = AnnotationUtils.findAnnotation(signature.getMethod(), SolrSynchro.class);
        if (Objects.nonNull(solrSynchro))
        {
            return solrSynchro;
        }

        return AnnotationUtils.findAnnotation(signature.getDeclaringType(), SolrSynchro.class);
    }


}

6.4使用注解进行同步在service实现类使用同步注解同步

	@SolrSynchro(type = "notice",coreName = "search",method = "INSERT")
    public int inserttest(WebNotice webNotice)
    {
       
    }

参考文章:
https://www.cnblogs.com/zouwangblog/p/12171015.html
https://blog.csdn.net/vtopqx/article/details/73224510
https://www.jianshu.com/p/05a161add1a6

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值