Lucene複習:html
一、什麼是lucene:全文檢索工具包前端
二、Lucene的工做原理:java
索引數據的建立mysql
從原始文件中提取一些能夠用來搜索的數據(封裝成各類Field),把各field再封裝成document,而後對document進行分析(對各字段分詞),獲得一些索引目錄寫入索引庫,document自己也會被寫入一個文檔信息庫;程序員
索引數據的查詢web
根據關鍵詞解析(queryParser)出查詢條件query(Termquery),利用搜索工具(indexSearcher)去索引庫獲取文檔id,而後再根據文檔id去文檔信息庫獲取文檔信息spring
分詞器不一樣,創建的索引數據就不一樣;比較通用的一箇中文分詞器IKAnalyzer的用法sql
三、相關度得分數據庫
a) 在創建索引的時候,給指定文檔的指定域設置一個權重apache
Field.setBoosts()
b) 在搜索的時候,能夠給不一樣的搜索域設置不一樣的權重
Boosts = new HashMap<String,Float>
MultiFieldsQueryParser(fields,analyzer,boosts)
Solr筆記
一、站內搜索技術選型。
二、Solr相關概念
三、Solr的安裝及配置
Solr整合tomcat
四、solr後臺管理界面的功能介紹
a) 維護索引
b) 查詢索引
五、solr實現索引庫的維護
a) 增刪改操做
b) 批量添加數據,從數據庫中把數據導入到索引庫。Dataimport插件。
六、索引庫的查詢
七、SolrJ客戶端,
a) 索引庫的維護
b) 索引庫的查詢
八、綜合案例,電商網站的搜索。
一、Lucene:能夠實現站內搜索。須要大量的開發工做。索引庫的維護及優化。查詢的優化等問題都須要咱們本身來解決。不推薦使用。
二、使用第三方搜素引擎實現。使用百度實現站內搜索。免費的。索引庫沒法維護。適合一些小的網站。不推薦使用。
三、Solr:基於Solr實現站內搜索擴展性較好而且能夠減小程序員的工做量,由於Solr提供了較爲完備的搜索引擎解決方案,所以在門戶、論壇等系統中經常使用此方案。提供了完整的集羣方案,和索引庫優化方案。
爲何要solr:
一、solr是將整個索引操做功能封裝好了的搜索引擎系統(企業級搜索引擎產品)
二、solr能夠部署到單獨的服務器上(WEB服務),它能夠提供服務,咱們的業務系統就只要發送請求,接收響應便可,下降了業務系統的負載
三、solr部署在專門的服務器上,它的索引庫就不會受業務系統服務器存儲空間的限制
四、solr支持分佈式集羣,索引服務的容量和能力能夠線性擴展
solr的工做機制:
一、solr就是在lucene工具包的基礎之上進行了封裝,並且是以web服務的形式對外提供索引功能
二、業務系統須要使用到索引的功能(建索引,查索引)時,只要發出http請求,並將返回數據進行解析便可
Solr 是Apache下的一個頂級開源項目,採用Java開發,它是基於Lucene的全文搜索服務器。Solr提供了比Lucene更爲豐富的查詢語言,同時實現了可配置、可擴展,並對索引、搜索性能進行了優化。
Solr能夠獨立運行,運行在Jetty、Tomcat等這些Servlet容器中,Solr 索引的實現方法很簡單,用 POST 方法向 Solr 服務器發送一個描述 Field 及其內容的 XML 文檔,Solr根據xml文檔添加、刪除、更新索引 。Solr 搜索只須要發送 HTTP GET 請求,而後對 Solr 返回Xml、json等格式的查詢結果進行解析,組織頁面佈局。Solr不提供構建UI的功能,Solr提供了一個管理界面,經過管理界面能夠查詢Solr的配置和運行狀況。
就是一個web工程
Lucene是一個開放源代碼的全文檢索引擎工具包,它不是一個完整的全文檢索引擎,Lucene提供了完整的查詢引擎和索引引擎,目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者以Lucene爲基礎構建全文檢索引擎。
Solr的目標是打造一款企業級的搜索引擎系統,它是一個搜索引擎服務,能夠獨立運行,經過Solr能夠很是快速的構建企業的搜索引擎,經過Solr也能夠高效的完成站內搜索功能。
最新版:5.3.1
本課程的版本:4.10.3
安裝solr,就是去部署它的war包,war包所在的位置如圖:
Jdk:1.7以上。1.7.0_72
Tomcat:7以上。apache-tomcat-7.0.53
Solr:4.10.3
第一步:安裝tomcat,建議安裝一個全新的tomcat。
第二步:上傳solr安裝壓縮包到服務器上,而後解壓
unzip -q /root/solr-4.10.3.zip
第三步:在tomcat的webapps中事先創建一個solr工程文件夾
mkdir /usr/local/apache-tomcat-7.0.63/webapps/solr
而後將solr的war包解壓到solr工程文件夾裏面去
unzip /root/solr-4.10.3/dist/solr-4.10.3.war -d /usr/local/apache-tomcat-7.0.63/webapps/solr
而後,將日誌工具jar包添加到solr的war工程的WebInf的lib中
cp /root/solr-4.10.3/example/lib/ext/*.jar /usr/local/apache-tomcat-7.0.63/webapps/solr/WEB-INF/lib/
第四步:從solr的安裝目錄中拷貝一個示例solrhome到咱們的服務器真實部署目錄中
拷貝: cp -r /root/solr-4.10.3/example/solr /usr/local/
更名: mv /usr/local/solr/ /usr/local/solrhome
第五步:告訴solr的war工程,咱們準備的solrhome目錄所在的路徑
vi /usr/local/apache-tomcat-7.0.63/webapps/solr/WEB-INF/web.xml
至此,能夠啓動tomcat,進行測試
瞭解solrhome:
一、collection1:是一個solrcore,一個solrcore就是一個索引庫。一個solr服務器上能夠有多solrcore。每一個索引庫之間是相互獨立的。
二、\solrhome\collection1\conf:是存放每一個solrcore的個性配置。
三、Solrconfig.xml
a) luceneMatchVersion:匹配lucene的版本信息
b) Lib:solrcore擴展使用的jar包。默認值是collection1\lib,若是沒有此文件夾就建立一個。
c) dataDir:索引庫存放的目錄。默認是collection1\data文件夾。若是沒有solr會自動建立。若是想修改成其餘位置,須要配置此節點。
d) requestHandler:配置solr對外提供服務的url
i. <requestHandler name="/select" class="solr.SearchHandler">:查詢索引庫使用的url
ii. <requestHandler name="/update" class="solr.UpdateRequestHandler">
維護索引庫使用的url
e) defaultQuery:管理頁面默認的查詢條件 *:*
四、Core.properties:配置了solrcore的名字。
第六步:告訴solr工程solrhome的位置。修改solr/WEB-INF/web.xml文件。
第七步:啓動tomcat
訪問http://localhost:8080/solr
solrcore的管理 功能。
添加步驟:
第一步:把collection1複製一份更名爲collection2
第二步:修改core.properties。name=collection2
第三步:重啓tomcat
選擇要管理哪一個solrcore。
查看域的分詞效果。
能夠實現把數據庫中的數據導入到索引庫中。
索引庫維護功能。
增刪改查
索引查詢功能。
在solr中域必須先定義後使用。並且每一個document中必須有一個id域。
Name:域的名稱
Type:域的類型
Indexed:是否索引
Stored:是否存儲
multiValued:是否多值,若是是多值在一個域中能夠保持多個值。
Name:域的名稱,是一個表達式。若是域的名稱和表達式相匹配,此域名就可使用。
Type:域的類型
Indexed:是否索引
Stored:是否存儲
multiValued:是否多值,若是是多值在一個域中能夠保持多個值。
每一個文檔必須有一個uniqueKey,並且不能重複。至關於表中的主鍵。
複製域。
Source:源域
Dest:目標域。
建立文檔時,solr會自動把源域的內容複製到目標域。使用複製域能夠提供查詢的性能。
域的類型。
Name:域類型名。
Class:對應的實現類。solr.TextField相似於Lucene中的TextField。能夠配置用戶自定義的分析器。
配置步驟:
第一步:把IKAnalyzer2012FF_u1.jar添加到solr工程的lib庫中。
第二步:把配置文件和擴展詞典、停用詞詞典添加到solr工程classpath下。Solr/WEB-INF/classes。保證字典的字符集是utf-8.
在schema.xml中添加以下內容:
<!-- IKAnalyzer--> <fieldType name="text_ik" class="solr.TextField"> <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/> </fieldType> <!--IKAnalyzer Field--> |
<field name="title_ik" type="text_ik" indexed="true" stored="true" /> <field name="content_ik" type="text_ik" indexed="true" stored="false" multiValued="true"/> |
<!--product--> <field name="product_name" type="text_ik" indexed="true" stored="true"/> <field name="product_price" type="float" indexed="true" stored="true"/> <field name="product_description" type="text_ik" indexed="true" stored="false" /> <field name="product_picture" type="string" indexed="false" stored="true" /> <field name="product_catalog_name" type="string" indexed="true" stored="true" /> <field name="product_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/> <copyField source="product_name" dest="product_keywords"/> <copyField source="product_description" dest="product_keywords"/> |
注意:每一個文檔必須有一個id域。並且域名必須在schema.xml中定義。
能夠批量把數據庫中的數據導入到索引庫中。
第一步:把dataimport插件依賴的jar包添加到collection1\lib文件夾下。
第二步:把mysql的數據庫驅動也放到collection1\lib文件夾下
第三步:修改solrhome/collection1/conf/solrconfig.xml,添加一個requestHandler。
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler"> <lst name="defaults"> <str name="config">data-config.xml</str> </lst> </requestHandler> |
第四步:建立一個data-config.xml。目錄和solrconfig.xml在同一個目錄下collection1\conf。
<?xml version="1.0" encoding="UTF-8" ?> <dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://192.168.33.10:3306/taotao" user="root" password="root"/> <document> <entity name="product" query="SELECT pid,name,catalog_name,price,description,picture FROM products "> <field column="pid" name="id"/> <field column="name" name="product_name"/> <field column="catalog_name" name="product_catalog_name"/> <field column="price" name="product_price"/> <field column="description" name="product_description"/> <field column="picture" name="product_picture"/> </entity> </document> </dataConfig> |
第五步:重啓tomcat後,進入solr管理頁面,執行數據導入
q:主查詢條件。徹底支持lucene語法。還進行了擴展。
fq:過濾查詢。是在主查詢條件查詢結果的基礎上進行過濾。
sort:排序條件。排序的域asc。若是有多個排序條件使用半角逗號分隔。
start, rows:分頁處理。Start起始記錄rows每頁顯示的記錄條數。
fl:返回結果中域的列表。使用半角逗號分隔。
df:默認搜索域
wt:響應結果的數據格式,能夠是json、xml等。
hl:開啓高亮顯示。
hl.fl:要高亮顯示的域。
hl.simple.pre:高亮顯示的前綴
hl.simple.post:高亮顯示的後綴
能夠實現對索引庫的增刪改查操做。
第一步:建立一java工程。
第二步:導入jar包。導入solrj的jar 包。
第1步:建立SolrServer對象和服務端創建鏈接。HttpSolrServer子類來完成。集羣環境使用CloudSolrServer。
第2步:建立一文檔對象。SolrInputDocument。
第3步:向文檔對象中添加域。使用addField添加域。要求必須有id域,並且每一個域必須在schema.xml中定義。
第4步:使用solrServer對象把文檔提交到服務器。
//添加文檔對象 @Test public void addDocument() throws Exception { //建立一個SolrServer對象 //參數:solr服務器的url SolrServer server = new HttpSolrServer("http://localhost:8080/solr"); //建立文檔對象 SolrInputDocument document = new SolrInputDocument(); //添加域 document.addField("id", "num001"); document.addField("title_ik", "巧手DIY彩簾"); //把document對象寫入索引庫 server.add(document); //提交修改 server.commit(); } |
//根據id刪除文檔 @Test public void deleteDocumentById() throws Exception { SolrServer server = new HttpSolrServer("http://localhost:8080/solr"); //刪除文檔 server.deleteById("num001"); //提交修改 server.commit(); } |
//根據查詢刪除文檔 @Test public void deleteDocumentByQuery() throws Exception { SolrServer server = new HttpSolrServer("http://localhost:8080/solr"); //根據查詢條件刪除 server.deleteByQuery("*:*"); //提交修改 server.commit(); } |
Solrj並無一個方法能夠修改文檔。仍是使用add方法。只須要添加一個新的文檔,保證新文檔的id和被修改文檔的id一致便可。
本質先刪除後添加。
第一步:建立一個solrServer對象。
第二步:建立一個solrQuery對象。
第三步:向solrQuery對象中添加查詢條件。
第四步:執行查詢。返回文檔列表。
第五步:遍歷列表。
//簡單查詢 @Test public void queryIndex() throws Exception { SolrServer server = new HttpSolrServer("http://localhost:8080/solr"); //建立一個查詢對象 SolrQuery query = new SolrQuery(); //添加查詢條件 //query.setQuery("*:*"); query.set("q", "*:*"); //執行查詢 QueryResponse response = server.query(query); //取文檔列表 SolrDocumentList solrDocumentList = response.getResults(); System.out.println("查詢結果的總數量:" + solrDocumentList.getNumFound()); //遍歷列表 for (SolrDocument solrDocument : solrDocumentList) { System.out.println(solrDocument.get("id")); System.out.println(solrDocument.get("product_name")); System.out.println(solrDocument.get("product_price")); System.out.println(solrDocument.get("product_catalog_name")); System.out.println(solrDocument.get("product_picture")); } } |
使用Solr實現電商網站中商品信息搜索功能,能夠根據關鍵字、分類、價格範圍搜索商品信息,也能夠根據價格進行排序。
一、數據庫的表結構。
二、頁面原型圖。
三、業務流程圖
功能:查詢solr服務返回一個商品列表。須要一個query對象,執行query對象進行查詢,返回商品列表。
參數:SolrQuery query
返回值:ResultModel 包含商品列表
商品的pojo:
public class ProductModel { // 商品編號 private String pid; // 商品名稱 private String name; // 商品分類名稱 private String catalog_name; // 價格 private float price; // 商品描述 private String description; // 圖片名稱 private String picture; } |
返回值Pojo:
public class ResultModel { // 商品列表 private List<ProductModel> productList; // 商品總數 private Long recordCount; // 總頁數 private int pageCount; // 當前頁 private int curPage; } |
方法定義:
ResultModel queryProduct(SolrQuery query) throws Exception;
功能:接收controller傳遞過來的參數。建立一SolrQuery對象,拼裝查詢條件調用Dao層執行查詢返回一個ResultModel對象。還須要計算商品列表的總頁數。
參數:
一、查詢條件:String queryString
二、商品分類名稱:String catalog_name
三、價格區間過濾條件:使用一個字符串來描述一個區間例如:
*-10,10-20,20-30,30-*。
String price
四、排序條件:只須要接收一個排序的方式就能夠了。0:升序1:降序。 String sort
五、分頁條件:接收一個頁碼是一個Integer數據。須要咱們肯定每頁顯示商品的數量。能夠定義在常量或者配置文件。每頁顯示60商品。Integer page
返回值:ResultModel
方法定義:
ResultModel queryProduct(String queryString, String catalog_name, String price,String sort, Integer page);
功能:接收頁面傳遞過來的參數,調用service查詢商品列表。把查詢結果傳遞給頁面。還須要參數回顯。
參數:
1. 查詢條件:String queryString
2. 商品分類名稱:String catalog_name
3. 價格區間過濾條件:使用一個字符串來描述一個區間例如:
*-10,10-20,20-30,30-*。
String price
4. 排序條件:只須要接收一個排序的方式就能夠了。0:升序1:降序。 String sort
5. 分頁條件:接收一個頁碼是一個Integer數據。須要咱們肯定每頁顯示商品的數量。能夠定義在常量或者配置文件。每頁顯示60商品。Integer page
六、Model,傳遞參數使用。
返回值:String(邏輯視圖名)
方法定義:
Public String queryProduct(String queryString, String catalog_name, String price,String sort, Integer page, Model model)
第一步:建立一web工程
第二步:導入jar包。須要springmvc、spring、solrj、solrj依賴的jar、日誌相關的jar包。
第三步:編寫dao
第四步:編寫Service
第五步:編寫Controller
第六步:配置前端控制器,建立springmvc.xml配置三大件。
@Repository public class ProductDaoImpl implements ProductDao { @Autowired private SolrServer solrServer; @Override public ResultModel queryProduct(SolrQuery query) throws Exception { //根據query對象查詢索引庫 QueryResponse response = solrServer.query(query); //取商品列表 SolrDocumentList documentList = response.getResults(); List<ProductModel> productList = new ArrayList<>(); for (SolrDocument solrDocument : documentList) { //取商品信息 ProductModel productModel = new ProductModel(); productModel.setPid((String) solrDocument.get("id")); //取高亮顯示 String productName = ""; Map<String, Map<String, List<String>>> highlighting = response.getHighlighting(); List<String> list = highlighting.get(solrDocument.get("id")).get("product_name"); if (list != null && list.size() > 0) { productName = list.get(0); } else { productName = (String) solrDocument.get("product_name"); } productModel.setName(productName); productModel.setCatalog_name((String) solrDocument.get("product_catalog_name")); productModel.setPrice((float) solrDocument.get("product_price")); productModel.setPicture((String) solrDocument.get("product_picture")); //添加到商品列表 productList.add(productModel); } //返回值對象 ResultModel resultModel = new ResultModel(); resultModel.setProductList(productList); //查詢結果總數量 resultModel.setRecordCount(documentList.getNumFound()); return resultModel; } } |
@Service public class ProductServiceImpl implements ProductService { @Autowired private ProductDao productDao; @Override public ResultModel queryProduct(String queryString, String catalog_name, String price, String sort, Integer page) throws Exception { //拼裝查詢條件 SolrQuery solrQuery = new SolrQuery(); //查詢條件 if (null != queryString && !"".equals(queryString)) { solrQuery.setQuery(queryString); } else { solrQuery.setQuery("*:*"); } //分類名稱過濾條件 if (null != catalog_name && !"".equals(catalog_name)) { solrQuery.addFilterQuery("product_catalog_name:" + catalog_name); } //價格區間過濾條件 if (null != price && !"".equals(price)) { String[] strings = price.split("-"); solrQuery.addFilterQuery("product_price:["+strings[0]+" TO "+strings[1]+"]"); } //排序條件 if ("1".equals(sort)) { solrQuery.setSort("product_price", ORDER.desc); } else { solrQuery.setSort("product_price", ORDER.asc); } //分頁條件 if (page == null) page = 1; int start = (page - 1) * Global.PAGE_SIZE; solrQuery.setStart(start); solrQuery.setRows(Global.PAGE_SIZE); //設置默認搜索域 solrQuery.set("df", "product_keywords"); //高亮顯示 solrQuery.setHighlight(true); //高亮顯示的域 solrQuery.addHighlightField("product_name"); //前綴 solrQuery.setHighlightSimplePre("<span style=\"color:red\">"); //後綴 solrQuery.setHighlightSimplePost("</span>"); //執行查詢 ResultModel resultModel = productDao.queryProduct(solrQuery); //計算總頁數 Long recordCount = resultModel.getRecordCount(); int pageCount = (int) (recordCount / Global.PAGE_SIZE); if (recordCount % Global.PAGE_SIZE > 0) { pageCount ++; } resultModel.setPageCount(pageCount); resultModel.setCurPage(page); return resultModel; } } |
@Controller public class ProductController { @Autowired private ProductService productService; @RequestMapping("/list") public String queryProduct(String queryString, String catalog_name, String price, String sort, Integer page, Model model) { // 查詢商品列表 ResultModel resultModel = null; try { resultModel = productService.queryProduct(queryString, catalog_name, price, sort, page); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // 傳遞給頁面 model.addAttribute("result", resultModel); // 參數回顯 model.addAttribute("queryString", queryString); model.addAttribute("catalog_name", catalog_name); model.addAttribute("price", price); model.addAttribute("sort", sort); model.addAttribute("page", page); // 返回jsp return "product_list"; } } |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd "> <!-- 配置掃描包 --> <context:component-scan base-package="cn..jd" /> <!-- 配置註解驅動 --> <mvc:annotation-driven /> <!-- jsp視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前綴 --> <property name="prefix" value="/WEB-INF/jsp/"></property> <!-- 後綴 --> <property name="suffix" value=".jsp"></property> </bean> <bean class="org.apache.solr.client.solrj.impl.HttpSolrServer"> <constructor-arg value="http://localhost:8080/solr/"></constructor-arg> </bean> </beans> |
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>SolrJD0508</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 配置前端控制器 --> <!-- SpringMVC配置 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> <filter> <filter-name>Character Encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app> |