solr检索简单使用

1.背景需求

  项目中要使用solr进行简单的检索,需要满足一下要求

  1. 会议地点完全匹配检索
  2. 会议开始时间与会议结束时间区间检索
  3. 支持多字段组合关键字检索
  4. 支持分页
  5. 支持字段排序

2.solr简单搭建

  docker中搭建solr8.4版本的,安装ik分词器,这个步骤就不作详细描述,有需要的参考网上其他安装的文章

  solr官方地址:https://solr.apache.org/guide/8_9/query-syntax-and-parsing.html

3.在springboot整合

1.solr依赖

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

里面集成了solrj,并在springboot-aotuconfigure中自动注入和HttpSolrClient

2.配置文件

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

3.java模型模型

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.annotation.Id;

import java.io.Serializable;
import java.util.Date;
import java.util.List;


@Data
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class AddMeetingRecordDTO extends Model implements Serializable {

    private static final long serialVersionUID = 6089362063910683619L;

    public static final String MEETING_ID = "id";
    public static final String SUBJECT = "subject";
    public static final String START_DATE = "startDate";
    public static final String END_DATE = "endDate";
    public static final String ROOM_NAME = "roomName";
    public static final String LEADER_NAMES = "leaderNames";
    public static final String LEADER_IDS = "leaderIds";
    public static final String CREATOR_ID = "creatorId";
    

    @Id
    @Field("id")
    private String meetingId;

    @Field("subject")
    private String subject;

    @Field("startDate")
    private Date startDate;

    @Field("endDate")
    private Date endDate;

    @Field("roomName")
    private String roomName;
    
    @Field("leaderNames")
    private String leaderNames;

    @Field("leaderIds")
    private List<String> leaderIds;

    @Field("attenderNames")
    private List<String> attenderNames;

    @Field("attenderIds")
    private List<String> attenderIds;

    @Field("detailContent")
    private String detailContent;

    @Field("digestContent")
    private String digestContent;

    @Field("creatorId")
    private String creatorId;

}

4.solr中域(字段)的定义

<?xml version="1.0" encoding="UTF-8"?>

<schema name="default-config" version="1.6">
    
    <!--solr中已定义id域,其他域为自定义-->
    <field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
    
    <field name="subject" type="text_ik" uninvertible="true" indexed="true" required="true" stored="true"/>
    <field name="startDate" type="pdate" uninvertible="true" indexed="true" required="true" stored="true"/>
    <field name="endDate" type="pdate" uninvertible="true" indexed="true" required="true" stored="true"/>
    <field name="roomName" type="string" uninvertible="true" indexed="true" required="true" stored="true"/>
    <field name="leaderNames" type="string" uninvertible="true" indexed="true" required="true" stored="true"/>
    <field name="leaderIds" type="string" uninvertible="true" multiValued="true" indexed="true" required="true" stored="true"/>
    <field name="attenderNames" type="text_ik" uninvertible="true" multiValued="true" indexed="true" required="true" stored="true"/>
    <field name="attenderIds" type="string" uninvertible="true" multiValued="true" indexed="true" required="false" stored="true"/>
    <field name="detailContent" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
    <field name="digestContent" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
    <field name="creatorId" type="string" uninvertible="true" indexed="true" required="true" stored="true"/>
    
    <!--组合检索字段-->
    <field name="subject_detail" type="text_ik" uninvertible="true" multiValued="true" indexed="true" stored="true"/>
    <copyField source="detailContent" dest="subject_detail"/>
    <copyField source="subject" dest="subject_detail"/>

    <!--组合检索字段-->
    <field name="subject_add" type="text_ik" uninvertible="true" multiValued="true" indexed="true" stored="true"/>
    <copyField source="attenderNames" dest="subject_add"/>
    <copyField source="detailContent" dest="subject_add"/>
    <copyField source="digestContent" dest="subject_add"/>
    <copyField source="subject" dest="subject_add"/>
</schema>

这个摘自managed-schema定义中

4.增删改查

1.新增/更新

@Resource
private HttpSolrClient solrClient;


1.insert
UpdateResponse updateResponse = solrClient.addBean(dto);
solrClient.commit();
//这里题主开始没有提交数据,导致插入后一直查不到数据,找了好久的问题
//solr的自动提交可以在配置文件中配置,我是因为没有设置自动提交,所以需要手动提交

2.update(根据id更新某个字段)
//solr中如果根据id查询到文档,就会覆盖,查询不到就会新增

HashMap<String, Object> operator = new HashMap<>();
operator.put("set", dto.getDigestContent());
SolrInputDocument doc = new SolrInputDocument();

doc.addField("meetingId", dto.getMeetingId());
doc.addField("digestContent", operator);

solrClient.add(doc);
solrClient.commit();

2.查询

//1.日期区间检索
StringBuilder builder = new StringBuilder();
builder.append("startDate:[ ").append(startDate.format(datetimeformatter)).append(" TO * ]");
builder.append(" && endDate:[ * TO ").append(endDate.format(datetimeformatter)).append(" ]");
//2.会议地点精确匹配,solr中要完全匹配,需要设置字段类型为string,并且值需要用双引号括起来
if (StrUtil.isNotEmpty(roomName)) {
    builder.append(" && roomName:\"").append(roomName).append("\"");
}
//3.分词匹配(相当于mysql中的模糊匹配)
if (StrUtil.isNotEmpty(searchField)) {
    builder.append(" && ").append(searchField).append(":").append(searchFieldValue);
}

SolrQuery solrQuery = new SolrQuery();
solrQuery.set(CommonParams.Q, builder.toString());

//分页中需要查询总条数total,所以设置开始和条数都为0
solrQuery.setStart(0);
solrQuery.setRows(0);

long total = solrClient.query(solrQuery).getResults().getNumFound();
if(total > 0){
    //solr排序
    solrQuery.addSort(sortField, SolrQuery.ORDER.asc);
    //设置分页数据
    solrQuery.setStart((pageNum - 1) * pageSize);
    solrQuery.setRows(pageSize);
    
    //设置需要查询出来的字段
    solrQuery.addField(MEETING_ID);
    solrQuery.addField(SUBJECT);
    solrQuery.addField(START_DATE);
    
    QueryResponse response = solrClient.query(solrQuery);
    SolrDocumentList documentList = response.getResults();
    
    documentList.forEach(item -> {
     //取出数据 String meetingIdStr
= (String) item.get(MEETING_ID); String subjectStr = (String) item.get(SUBJECT); Date startDateAlis = (Date) item.get(START_DATE); Date endDateAlis = (Date) item.get(END_DATE); List<String> leaderIdList = (List) item.get(LEADER_IDS); //业务逻辑处理 } }

 ============over ============

posted @ 2021-08-26 14:46  meow_world  阅读(213)  评论(2)    收藏  举报