solr的認識、linux下安裝、java下使用(含下載資源)

来源:https://www.cnblogs.com/ranandrun/archive/2019/04/25/solr.html
-Advertisement-
Play Games

目錄: 一、solr的大概認識 二、solr安裝 三、solr的深度認識 四、solr的使用 (1)由於我們用到中文,所以需要中文分析器,這裡我用IK Analyzer 2012FF_hf1 (2)同時在schema.xml指定好業務域 field name...... (3)同時在schema.x ...


目錄

一、solr的大概認識

(1)在互聯網項目裡面,絕大部分是用全文檢索伺服器,
lucense(基於java的全文檢索api)和solr(基於lucense的全文檢索伺服器)都可以實現。用lucense需要自己來管理維護索引庫,進行索引庫的優化,緩存的添加。而solr配置一下就好了,比較方便。
(2)solr本質上是一個war包,然後部署到servlet容器中,容器你可以選擇用tomcat,也可以選擇更加輕量級的jetty
(3)反正solr就是:比如 好多好多商品,每個都好長名字。那我比如搜索 '漂亮手機' 的時候,solr自動劃分欄位(比如劃分成 ‘漂亮’,‘手機’),自動去匹配資料庫中對應的商品名列表,商品名列表也會被劃分,完全匹配的就會展示出來
(4)solr使用的時候分兩部分:把商品名列表放到solr;搜索商品

二、solr安裝

(1)安裝jdk(省略)
(2)下載 solr-4.10.3.tgz.tgz並解壓
鏈接:https://pan.baidu.com/s/1G6-aLXboFKThzRiDtUV-Xg
提取碼:0j9o
(3)安裝tomcat(省略)
(4)拷貝solr的war包到tomcat下

[root@localhost apache-tomcat-7.0.47]# cp /usr/solr/solr-4.10.3/dist/solr-4.10.3.war webapps/solr.war

(5)啟動tomcat自動解壓縮war包:

[root@localhost apache-tomcat-7.0.47]# bin/startup.sh

(6)查看控制台,檢查tomcat啟動情況:

[root@localhost apache-tomcat-7.0.47]# tail -f logs/catalina.out

(7)關閉tomcat

[root@localhost apache-tomcat-7.0.47]# bin/shutdown.sh

(8)刪除war包

[root@localhost apache-tomcat-7.0.47]# rm -f webapps/solr.war

(9)把一些jar包放到solr工程下麵去:

[root@localhost apache-tomcat-7.0.47]# cp /usr/solr/solr-4.10.3/example/lib/ext/* webapps/solr/WEB-INF/lib/

(10)配置solrhome

[root@localhost solr-4.10.3]# cp -r example/solr /usr/solr/solrhome
[root@localhost apache-tomcat-7.0.47]# cd webapps/solr/WEB-INF/
[root@localhost WEB-INF]# vim web.xml

修改solr/home的地址,並且去掉註釋

(11)再次開啟tomcat

[root@localhost apache-tomcat-7.0.47]# bin/startup.sh

(12)在Windows那邊訪問solr
http://192.168.25.128:8080/solr/

三、solr的深度認識

用戶可以通過http請求,向搜索引擎伺服器提交一定格式的XML文件或數據,生成索引;也可以通過Http Get操作提出查找請求,並得到XML格式的返回結果。

四、solr的使用

(1)由於我們用到中文,所以需要中文分析器,這裡我用IK Analyzer 2012FF_hf1

鏈接:https://pan.baidu.com/s/15TUJaTJir9d0A0FRaiBl_A
提取碼:5xrw

下載好IK Analyzer 2012FF_hf1文件後,安裝步驟:
<1>拷貝IKAnalyzer2012FF_u1.jar到tomcat的solr項目下的lib中:

[root@localhost apache-tomcat-7.0.47]# cd webapps/solr/WEB-INF/lib
[root@localhost lib]# cp /usr/solr/IK_Analyzer_2012FF_hf1/IKAnalyzer2012FF_u1.jar .

<2>拷貝三個文件到tomcat的solr項目下的classes文件中

[root@localhost lib]# cd ..
[root@localhost WEB-INF]# mkdir classes
[root@localhost IK_Analyzer_2012FF_hf1]# cp ext_stopword.dic IKAnalyzer.cfg.xml mydict.dic /usr/tomcat/apache-tomcat-7.0.47/webapps/solr/WEB-INF/classes

<3>在solrhome裡面的schema.xml定義一個fieldtype,來指定IK分析器。

  <fieldType name="text_ik" class="solr.TextField">
    <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
  </fieldType>

(2)同時在schema.xml指定好業務域 field name......

由於solr本身就定義了id,所以我們用solr的id來保存我們要的id就可以了。
註意:string類型的是不可拆分的,而TextField類型的是可拆分的

<field name="item_title" type="text_ik" indexed="true" stored="true"/>
<field name="item_sell_point" type="text_ik" indexed="true" stored="true"/>
<field name="item_price"  type="long" indexed="true" stored="true"/>
<field name="item_image" type="string" indexed="false" stored="true" />
<field name="item_category_name" type="string" indexed="true" stored="true" />
<field name="item_desc" type="text_ik" indexed="true" stored="false" />

(3)同時在schema.xml配置複製域

就是說你找一個商品的時候,可以在item_keywords中的四個域中找

<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="item_title" dest="item_keywords"/>
<copyField source="item_sell_point" dest="item_keywords"/>
<copyField source="item_category_name" dest="item_keywords"/>
<copyField source="item_desc" dest="item_keywords"/>

(4)啟動solr看看業務域是否能用

[root@localhost apache-tomcat-7.0.47]# bin/startup.sh

進入http://192.168.25.128:8080/solr/裡面的collection1的Analyse ,選擇一個域,比如:

五、用java代碼增刪data到solr中

(1)導包

<!-- 添加solrJ的依賴 -->
        <dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solr-solrj</artifactId>
        </dependency>

(2)測試一下

import org.apache.solr.client.solrj.SolrServer;
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 org.apache.solr.common.SolrInputDocument;
import org.junit.Test;

public class TestSolrJ {

    @Test
    public void testAddDocument() throws Exception {
        //創建一個SolrServer對象。創建一個HttpSolrServer對象
        //需要指定solr服務的url
        SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
        //創建一個文檔對象SolrInputDocument
        SolrInputDocument document = new SolrInputDocument();
        //向文檔中添加域,必須有id域,域的名稱必須在schema.xml中定義
        document.addField("id", "1234");
        document.addField("item_title", "測試商品2");
        document.addField("item_price", 1000);
        //把文檔對象寫入索引庫
        solrServer.add(document);
        //提交
        solrServer.commit();
    }
    
    @Test
    public void deleteDocumentById() throws Exception {
        SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
        solrServer.deleteById("123");
        //提交
        solrServer.commit();
    }
    
    @Test
    public void deleteDocumentByQuery() throws Exception {
        SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
        solrServer.deleteByQuery("item_title:測試商品3");
        solrServer.commit();
    }
}
    

六、實際開發中導入資料庫數據到solr的data中的步驟

<1>定義一個 (將資料庫的部分數據導入到solr的data中的)介面

import com.wine.common.pojo.WineResult;
public interface SearchItemService {
    WineResult importItemsToIndex();
}

<2>實現上方介面

@Service
public class SearchItemServiceImpl implements SearchItemService {

    @Autowired
    private SearchItemMapper searchItemMapper;
    @Autowired
    private SolrServer solrServer;
    
    @Override
    public WineResult importItemsToIndex() {
        try {
            //1、先查詢所有商品數據
            List<SearchItem> itemList = searchItemMapper.getItemList();
            //2、遍歷商品數據添加到索引庫
            for (SearchItem searchItem : itemList) {
                //創建文檔對象
                SolrInputDocument document = new SolrInputDocument();
                //向文檔中添加域
                document.addField("id", searchItem.getId());
                document.addField("item_title", searchItem.getTitle());
                document.addField("item_sell_point", searchItem.getSell_point());
                document.addField("item_price", searchItem.getPrice());
                document.addField("item_image", searchItem.getImage());
                document.addField("item_category_name", searchItem.getCategory_name());
                document.addField("item_desc", searchItem.getItem_desc());
                //把文檔寫入索引庫
                solrServer.add(document);
            }
            //3、提交
            solrServer.commit();
        } catch (Exception e) {
            e.printStackTrace();
            return WineResult.build(500, "數據導入失敗");
        }
        //4、返回添加成功
        return WineResult.ok();
    }

}

<3>solr連接文件applicationContext-solr.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
    
    <!-- 單機版solr的連接 -->
    <bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
        <constructor-arg name="baseURL" value="http://192.168.25.128:8080/solr/collection1"/>
    </bean>
    <!-- 集群版solr連接 -->
    <!-- <bean id="cloudSolrServer" class="org.apache.solr.client.solrj.impl.CloudSolrServer">
        <constructor-arg name="zkHost" value="192.168.25.128:2181,192.168.25.128:2182,192.168.25.128:2183"></constructor-arg>
        <property name="defaultCollection" value="collection2"/>
    </bean> -->
    
</beans>

七、實際開發中實現搜索功能步驟

(1)首先測試一下,輸入測試商品,看看搜索出什麼東西:

    @Test
    public void searchDocumet() throws Exception {
        //創建一個SolrServer對象
        SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
        //創建一個SolrQuery對象
        SolrQuery query = new SolrQuery();
        //設置查詢條件、過濾條件、分頁條件、排序條件、高亮
        //query.set("q", "*:*");
        query.setQuery("測試商品");
        //分頁條件
        query.setStart(0);
        query.setRows(10);
        //設置預設搜索域
        query.set("df", "item_keywords");
        //設置高亮
        query.setHighlight(true);
        //高亮顯示的域
        query.addHighlightField("item_title");
        query.setHighlightSimplePre("<div>");
        query.setHighlightSimplePost("</div>");
        
        //執行查詢,得到一個Response對象
        QueryResponse response = solrServer.query(query);
        //取查詢結果
        SolrDocumentList solrDocumentList = response.getResults();
        //取查詢結果總記錄數
        System.out.println("查詢結果總記錄數:" + solrDocumentList.getNumFound());
        for (SolrDocument solrDocument : solrDocumentList) {
            System.out.println(solrDocument.get("id"));
            //取高亮顯示
            Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
            List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
            String itemTitle = "";
            if (list != null && list.size() >0) {
                itemTitle = list.get(0);
            } else {
                itemTitle = (String) solrDocument.get("item_title");
            }
            System.out.println(itemTitle);
            System.out.println(solrDocument.get("item_sell_point"));
            System.out.println(solrDocument.get("item_price"));
            System.out.println(solrDocument.get("item_image"));
            System.out.println(solrDocument.get("item_category_name"));
            System.out.println("=============================================");
        }
        
    }

結果:(註意:sol按照匹配次數多的來排序)
我已經在solor中插入了數據(id,title,....):(123456, 測試商品2,...),(1,測試2商品,...),(2,2商品測試,...),(,7,66測試66商品,...),(5,2測試,...),(6,2商品,...)

查詢結果總記錄數:6
123456
<div>測試</div><div>商品</div>2
null
1000
null
null
=============================================
1
<div>測試</div>2<div>商品</div>
null
1000
null
null
=============================================
2
2<div>商品</div><div>測試</div>
null
1000
null
null
=============================================
7
66<div>測試</div>66<div>商品</div>
null
1000
null
null
=============================================
5
2<div>測試</div>
null
1000
null
null
=============================================
6
2<div>商品</div>
null
1000
null
null
=============================================

(2)具體代碼實現

<1>添加一個訪問solr的dao:

/**
 * 查詢索引庫商品dao
 */
@Repository
public class SearchDao {
    
    @Autowired
    private SolrServer solrServer;
    /**
    SearchResult 這個pojo類裡面的數據:
    private long totalPages;
    private long recordCount;
    private List<SearchItem> itemList;
    **/
    public SearchResult search(SolrQuery query) throws Exception{
        //根據query對象進行查詢
        QueryResponse response = solrServer.query(query);
        //取查詢結果
        SolrDocumentList solrDocumentList = response.getResults();
        //取查詢結果總記錄數
        long numFound = solrDocumentList.getNumFound();
        SearchResult result = new SearchResult();
        result.setRecordCount(numFound);
        List<SearchItem> itemList = new ArrayList<>();
        //把查詢結果封裝到SearchItem對象中
        for (SolrDocument solrDocument : solrDocumentList) {
            SearchItem item = new SearchItem();
            item.setCategory_name((String) solrDocument.get("item_category_name"));
            item.setId((String) solrDocument.get("id"));
            //取一張圖片
            String image = (String) solrDocument.get("item_image");
            if (StringUtils.isNotBlank(image)) {
                image = image.split(",")[0];
            }
            item.setImage(image);
            item.setPrice((long) solrDocument.get("item_price"));
            item.setSell_point((String) solrDocument.get("item_sell_point"));
            //取高亮顯示
            Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
            List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
            String title = "";
            if (list != null && list.size() > 0) {
                title = list.get(0);
            } else {
                title = (String) solrDocument.get("item_title");
            }
            item.setTitle(title);
            //添加到商品列表
            itemList.add(item);
        }
        //把結果添加到SearchResult中
        result.setItemList(itemList);
        //返回
        return result;
    }
}

<2>添加調用dao的service類:

/**
 * 搜索服務功能實現
 */
@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    private SearchDao searchDao;
    
    @Override
    public SearchResult search(String queryString, int page, int rows) throws Exception {
        //根據查詢條件拼裝查詢對象
        //創建一個SolrQuery對象
        SolrQuery query = new SolrQuery();
        //設置查詢條件
        query.setQuery(queryString);
        //設置分頁條件
        if (page < 1) page =1;
        query.setStart((page - 1) * rows);
        if (rows < 1) rows = 10;
        query.setRows(rows);
        //設置預設搜索域
        query.set("df", "item_title");
        //設置高亮顯示
        query.setHighlight(true);
        query.addHighlightField("item_title");
        query.setHighlightSimplePre("<font color='red'>");
        query.setHighlightSimplePost("</font>");
        //調用dao執行查詢
        SearchResult searchResult = searchDao.search(query);
        //計算查詢結果的總頁數
        long recordCount = searchResult.getRecordCount();
        long pages =  recordCount / rows;
        if (recordCount % rows > 0) {
            pages++;
        }
        searchResult.setTotalPages(pages);
        //返回結果
        return searchResult;
    }

}

<3>控制層

@Controller
public class SearchController {
    
    @Autowired
    private SearchService searchService;
    
    @Value("${SEARCH_RESULT_ROWS}")
    private Integer SEARCH_RESULT_ROWS;

    @RequestMapping("/search")
    public String search(@RequestParam("q")String queryString, 
            @RequestParam(defaultValue="1")Integer page, Model model) throws Exception {
        //int a = 1/0;
        //調用服務執行查詢
        //把查詢條件進行轉碼,解決get亂碼問題
        queryString = new String(queryString.getBytes("iso8859-1"), "utf-8");
        SearchResult searchResult = searchService.search(queryString, page, SEARCH_RESULT_ROWS);
        //把結果傳遞給頁面
        model.addAttribute("query", queryString);
        model.addAttribute("totalPages", searchResult.getTotalPages());
        model.addAttribute("itemList", searchResult.getItemList());
        model.addAttribute("page", page);

        //返回邏輯視圖
        return "search";
        
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天在調試一個後臺的介面的時候,突然發現在network中找不到我發送的請求,也就是說,ajax沒有在瀏覽器的network中沒有顯示。。。。。第一次遇見這樣的情況,很苦惱,然後使用ajax中的error函數,看到了下麵的列印數據。 然後繼續網上百度“No Transport”的問題,發現網上大部分 ...
  • 在做單頁面應用程式時,一般頁面佈局頭尾兩塊都是固定在佈局頁面,中間為是路由入口。這時訪問頁面時頭部標題不會變,該問題的解決方案如下: 通過採用組件內路由衛士(beforeRouterEnter、beforeRouterUpdate)與路由元信息(meta) 來實現更新頭部標題信息。點擊查看文檔 be ...
  • 不學會怎麼處理對象,你在 JavaScript 道路就就走不了多遠。它們幾乎是 JavaScript 編程語言每個方面的基礎。事實上,學習如何創建對象可能是你剛開始學習的第一件事。 ...
  • ​如果第二次看到我的文章,歡迎右側掃碼訂閱我喲~ 👉 本文長度為2805字,建議閱讀8分鐘。 堅持原創,每一篇都是用心之作~ 有句話說得好,欲要使其毀滅,先要使其瘋狂。當你沉浸在緩存所帶來的系統tps飆升的喜悅中時,使你系統毀滅的種子也已經埋在其中。 而且,你所承載的tps越高,它所帶來的毀滅性更 ...
  • [TOC] 個人認為動態代理在設計模式中算是比較難的, 本篇文章將從無到有, 從一個簡單代碼示例開始迭代, 逐步深入講解動態代理思想. 場景引入 假設現在有一個坦克類, 它實現了 介面, 裡面有一個 移動的方法. 代碼如下: 為了能計算坦克移動所花費的時間我們打算在坦克的 方法的前後添加一些代碼, ...
  • 上篇我們從理論上瞭解了什麼是工廠方法模式,也知道了創建者類和產品類的主要作用是什麼。更重要的是,我們還學到了一個設計原則 依賴倒置原則 ,這個原則能推導出我們為什麼會使用工廠模式。 當然啦,上次還留下幾個指導方針幫助我們去遵循依賴倒置原則。所以,接下來,我們就利用這幾個方針,跟著方法,來重新設計下我 ...
  • 問題描述:eclipse中運行程式時,出現如下錯誤 解決辦法: 出現此類:無法初始化主類有可能是因為eclipse中Java的版本與JDK的版本不匹配,我開始用的時候eclipse中用的是Java se 11,而JDK用的是12.01版本,後來將JDK改成11版本就完美解決此問題了。 ...
  • Java、Php等語言中都有成熟的框架來解析Json數據,可以讓我們使用很少的代碼就把格式化好的json數據轉換成程式可識別的對象或者屬性,同時delphi中也有這樣的組件來實現此功能,即IsuperObject。如果還沒有這個組件的請在網上搜索下載或者在下麵留言處留下你的郵箱向本人索取。 下麵先說 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...