SpringBoot高級篇搜索Solr之 文檔新增與修改使用姿式

大多涉及到數據的處理,無非CURD四種操做,對於搜索SOLR而言,基本操做也能夠說就這麼幾種,在實際應用中,搜索條件的多樣性纔是重點,咱們在進入複雜的搜索以前,先來看一下如何新增和修改文檔java

<!-- more -->git

I. 環境準備

solr的基礎環境須要準備好,若是對這一塊有疑問的童鞋,能夠參考下上一篇博文: 《190510-SpringBoot高級篇搜索之Solr環境搭建與簡單測試github

1. 環境配置

在pom文件中,設置好對應的依賴spring

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from update -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    <java.version>1.8</java.version>
</properties>


<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>


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

由於咱們採用默認的solr訪問姿式,因此配置文件中能夠不加對應的參數,固然也能夠加上apache

打開 application.yml 配置文件api

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

若是咱們的solr加上了用戶名密碼訪問條件,參數中並無地方設置username和password,那應該怎麼辦?app

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

如上寫法,將用戶名和密碼寫入http的鏈接中maven

2. 自動裝配

咱們主要使用SolrTemplate來和Solr打交到,所以咱們須要先註冊這個bean,能夠怎麼辦?spring-boot

package com.git.hui.boot.solr.config;

import org.apache.solr.client.solrj.SolrClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.solr.core.SolrTemplate;

/**
 * Created by @author yihui in 19:49 19/5/10.
 */
@Configuration
public class SearchAutoConfig {

    @Bean
    @ConditionalOnMissingBean(SolrTemplate.class)
    public SolrTemplate solrTemplate(SolrClient solrClient) {
        return new SolrTemplate(solrClient);
    }
}

上面的配置是條件注入,只有當SolrTemplate對應的bean沒有被自動加載時,纔會加載,爲何要怎麼幹?學習

(能夠想想緣由...)

II. 使用姿式示例

咱們的操做主要依賴的是SolrTemplate,所以有必要在開始以前,看一下它的簽名

Spring的源碼中,能夠發現大多xxxTemplate都會實現一個xxxOperations 接口,而這個接口就是用來定義CURD的api,好比咱們看下 SolrOperations中與修改相關的api

default UpdateResponse saveBean(String collection, Object obj) {
	return saveBean(collection, obj, Duration.ZERO);
}

/**
 * Execute add operation against solr, which will do either insert or update with support for commitWithin strategy.
 *
 * @param collection must not be {@literal null}.
 * @param obj must not be {@literal null}.
 * @param commitWithin max time within server performs commit.
 * @return {@link UpdateResponse} containing update result.
 */
UpdateResponse saveBean(String collection, Object obj, Duration commitWithin);

default UpdateResponse saveBeans(String collection, Collection<?> beans) {
	return saveBeans(collection, beans, Duration.ZERO);
}

UpdateResponse saveBeans(String collection, Collection<?> beans, Duration commitWithin);

default UpdateResponse saveDocument(String collection, SolrInputDocument document) {
	return saveDocument(collection, document, Duration.ZERO);
}

/**
 * Add a solrj input document to solr, which will do either insert or update with support for commitWithin strategy
 *
 * @param document must not be {@literal null}.
 * @param commitWithin must not be {@literal null}.
 * @return {@link UpdateResponse} containing update result.
 * @since 3.0
 */
UpdateResponse saveDocument(String collection, SolrInputDocument document, Duration commitWithin);


default UpdateResponse saveDocuments(String collection, Collection<SolrInputDocument> documents) {
	return saveDocuments(collection, documents, Duration.ZERO);
}

UpdateResponse saveDocuments(String collection, Collection<SolrInputDocument> documents, Duration commitWithin);

上面的api簽名中,比較明確的說明了這個 saveXXX 既能夠用來新增文檔,也能夠用來修改文檔,主要有提供了兩類

  • 單個與批量
  • saveDocument 與 saveBean

1. 添加文檔

從上面的api簽名上看,saveDocument 應該是相對原始的操做方式了,所以咱們先看下它的使用姿式

a. saveDocument

首先就是建立文檔 SolrInputDocument 對象,經過調用addField來設置成員值

public void testAddByDoc() {
    SolrInputDocument document = new SolrInputDocument();
    document.addField("id", 3);
    document.addField("title", "testAddByDoc!");
    document.addField("content", "經過solrTemplate新增文檔");
    document.addField("type", 2);
    document.addField("create_at", System.currentTimeMillis() / 1000);
    document.addField("publish_at", System.currentTimeMillis() / 1000);

    UpdateResponse response = solrTemplate.saveDocument("yhh", document);
    solrTemplate.commit("yhh");
    System.out.println("over:" + response);
}

<font color="red">注意:保存文檔以後,必定得調用commit提交</font>

b. saveBean

前面須要建立SolrInputDocument對象,咱們更但願的使用case是直接傳入一個POJO,而後自動與solr的filed進行關聯

所以一種使用方式能夠以下

  • 定義pojo,成員上經過 @Field 註解來關聯solr的field
  • pojo對象直接當作參數傳入,保存以後,執行 commit 提交
@Data
public static class DocDO {
    @Field("id")
    private Integer id;
    @Field("title")
    private String title;
    @Field("content")
    private String content;
    @Field("type")
    private Integer type;
    @Field("create_at")
    private Long createAt;
    @Field("publish_at")
    private Long publishAt;
}

/**
 * 新增
 */
private void testAddByBean() {
    DocDO docDO = new DocDO();
    docDO.setId(4);
    docDO.setTitle("addByBean");
    docDO.setContent("新增一個測試文檔");
    docDO.setType(1);
    docDO.setCreateAt(System.currentTimeMillis() / 1000);
    docDO.setPublishAt(System.currentTimeMillis() / 1000);

    UpdateResponse response = solrTemplate.saveBean("yhh", docDO);
    solrTemplate.commit("yhh");
    System.out.println(response);
}

c. 批量

批量的方式就比較簡單了,傳入集合便可

private void testBatchAddByBean() {
    DocDO docDO = new DocDO();
    docDO.setId(5);
    docDO.setTitle("addBatchByBean - 1");
    docDO.setContent("新增一個測試文檔");
    docDO.setType(1);
    docDO.setCreateAt(System.currentTimeMillis() / 1000);
    docDO.setPublishAt(System.currentTimeMillis() / 1000);

    DocDO docDO2 = new DocDO();
    docDO2.setId(6);
    docDO2.setTitle("addBatchByBean - 2");
    docDO2.setContent("新增一個測試文檔");
    docDO2.setType(1);
    docDO2.setCreateAt(System.currentTimeMillis() / 1000);
    docDO2.setPublishAt(System.currentTimeMillis() / 1000);

    UpdateResponse response = solrTemplate.saveBeans("yhh", Arrays.asList(docDO, docDO2));
    solrTemplate.commit("yhh");
    System.out.println(response);
}

d. 測試

上面的幾個方法,咱們執行以後,咱們看下是否能查詢到新增長的數據

output

2. 文檔修改

在看前面的接口簽名時,就知道修改和新增用的是相同的api,因此修改文檔和上面的使用實際上也沒有什麼特別的,下面簡單的演示一下

public void testUpdateDoc() {
    DocDO docDO = new DocDO();
    docDO.setId(5);
    docDO.setTitle("修改以後!!!");
    docDO.setType(1);
    docDO.setCreateAt(System.currentTimeMillis() / 1000);
    docDO.setPublishAt(System.currentTimeMillis() / 1000);

    UpdateResponse response = solrTemplate.saveBean("yhh", docDO);
    solrTemplate.commit("yhh");
    System.out.println(response);
}

上面的實例中,修改了id爲5的文檔標題,並刪除了content內容,執行完畢以後,結果如何呢?

output

  • title被替換
  • content沒有了

到這裏就有個疑問了,對於調用而言,怎麼保證是修改仍是新增呢?

  • 這裏主要是根據id來判斷,這個id相似db中的惟一主鍵,當咱們沒有指定id時,會隨機生成一個id
  • 若是存在相同的id,則修改文檔;若是不存在,則新增文檔

III. 其餘

0. 項目

1. 一灰灰Blog

盡信書則不如,以上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激

下面一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛

QrCode

相關文章
相關標籤/搜索