1. Solr的安裝及配置php
a) Solr整合tomcathtml
b) Solr後臺管理功能介紹java
c) 配置中文分析器mysql
2. 使用Solr的後臺管理索引庫程序員
a) 添加文檔web
b) 刪除文檔算法
c) 修改文檔spring
d) 查詢文檔sql
3. 使用SolrJ管理索引庫數據庫
a) 添加文檔
b) 修改文檔
c) 刪除文檔
d) 查詢文檔
4. 電商搜索案例實現
a) 案例分析
b) 案例實現
使用Solr實現電商網站中商品信息搜索功能,能夠根據關鍵字、分類、價格搜索商品信息,也能夠根據價格進行排序。
在一些大型門戶網站、電子商務網站等都須要站內搜索功能,使用傳統的數據庫查詢方式實現搜索沒法知足一些高級的搜索需求,好比:搜索速度要快、搜索結果按相關度排序、搜索內容格式不固定等,這裏就須要使用全文檢索技術實現搜索功能。
單獨使用Lucene實現站內搜索須要開發的工做量較大,主要表如今:索引維護、索引性能優化、搜索性能優化等,所以不建議採用。
基於Solr實現站內搜索擴展性較好而且能夠減小程序員的工做量,由於Solr提供了較爲完備的搜索引擎解決方案,所以在門戶、論壇等系統中經常使用此方案。
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的配置和運行狀況。
Solr與Lucene的區別:
Lucene是一個開放源代碼的全文檢索引擎工具包,它不是一個完整的全文檢索引擎,Lucene提供了完整的查詢引擎和索引引擎,目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者以Lucene爲基礎構建全文檢索引擎。
Solr的目標是打造一款企業級的搜索引擎系統,它是一個搜索引擎服務,能夠獨立運行,經過Solr能夠很是快速的構建企業的搜索引擎,經過Solr也能夠高效的完成站內搜索功能。
從Solr官方網站(http://lucene.apache.org/solr/ )下載Solr4.10.3,根據Solr的運行環境,Linux下須要下載lucene-4.10.3.tgz,windows下須要下載lucene-4.10.3.zip。
Solr使用指南可參考:https://wiki.apache.org/solr/FrontPage。
將solr-4.10.3.zip解壓:
bin:solr的運行腳本
contrib:solr的一些貢獻軟件/插件,用於加強solr的功能。
dist:該目錄包含build過程當中產生的war和jar文件,以及相關的依賴文件。
docs:solr的API文檔
example:solr工程的例子目錄:
該目錄叫作solrHome,是一個包含了默認配置信息的Solr的Core目錄。
該目錄包含了在Solr的multicore中設置的多個Core目錄。
該目錄中包括一個solr.war,該war可做爲solr的運行實例工程。
licenses:solr相關的一些許可信息
solr 須要運行在一個Servlet容器中,Solr4.10.3要求jdk使用1.7以上,Solr默認提供Jetty(java寫的Servlet容器),這裏使用Tocmat做爲Servlet容器,環境以下:
Solr:Solr4.10.3
Jdk:jdk1.7.0_72
Tomcat:apache-tomcat-7.0.53
建立一個Solr home目錄,SolrHome是Solr運行的主目錄,目錄中包括了運行Solr實例全部的配置文件和數據文件,Solr實例就是SolrCore,一個SolrHome能夠包括多個SolrCore(Solr實例),每一個SolrCore提供單獨的搜索和索引服務。
example\solr是一個solr home目錄結構,以下:
上圖中「collection1」是一個SolrCore(Solr實例)目錄 ,目錄內容以下所示:
說明:
collection1:叫作一個Solr運行實例SolrCore,SolrCore名稱不固定,一個solr運行實例對外單獨提供索引和搜索接口。
solrHome中能夠建立多個solr運行實例SolrCore。
一個solr的運行實例對應一個索引目錄。
conf是SolrCore的配置文件目錄 。
data目錄存放索引文件須要建立
第一步:安裝tomcat。D:\temp\apache-tomcat-7.0.53
第二步:把solr的war包複製到tomcat 的webapp目錄下。
把\solr-4.10.3\dist\solr-4.10.3.war複製到D:\temp\apache-tomcat-7.0.53\webapps下。
更名爲solr.war
第三步:solr.war解壓。使用壓縮工具解壓或者啓動tomcat自動解壓。解壓以後刪除solr.war
第四步:把\solr-4.10.3\example\lib\ext目錄下的全部的jar包(日誌)添加到solr工程中
第五步:配置solrHome和solrCore。
1)建立一個solrhome(存放solr全部配置文件的一個文件夾)。\solr-4.10.3\example\solr目錄就是一個標準的solrhome。
2)把\solr-4.10.3\example\solr文件夾複製到D:\temp\0108路徑下,更名爲solrhome,更名不是必須的,是爲了便於理解。
3)在solrhome下有一個文件夾叫作collection1這就是一個solrcore。就是一個solr的實例。一個solrcore至關於mysql中一個數據庫。Solrcore之間是相互隔離。
Xml的配置信息:
Lib:solr服務依賴的擴展包,默認的路徑是collection1\lib文件夾,若是沒有就建立一個
dataDir:配置了索引庫的存放路徑。默認路徑是collection1\data文件夾,若是沒有data文件夾,會自動建立。
requestHandler:
第六步:告訴solr服務器配置文件也就是solrHome的位置。修改web.xml使用jndi的方式告訴solr服務器。
Solr/home名稱必須是固定的。
第七步:啓動tomcat
第八步:訪問http://localhost:8080/solr/
儀表盤,顯示了該Solr實例開始啓動運行的時間、版本、系統資源、jvm等信息。
Solr運行日誌信息
Cloud即SolrCloud,即Solr雲(集羣),當使用Solr Cloud模式運行時會顯示此菜單,以下圖是Solr Cloud的管理界面:
Solr Core的管理界面。Solr Core 是Solr的一個獨立運行實例單位,它能夠對外提供索引和搜索服務,一個Solr工程能夠運行多個SolrCore(Solr實例),一個Core對應一個索引目錄。
添加solrcore:
第一步:複製collection1更名爲collection2
第二步:修改core.properties。name=collection2
第三步:重啓tomcat
Solr在JVM 運行環境中的屬性信息,包括類路徑、文件編碼、jvm內存設置等信息。
顯示Solr Server中當前活躍線程信息,同時也能夠跟蹤線程運行棧信息。
選擇一個SolrCore進行詳細操做,以下:
經過此界面能夠測試索引分析器和搜索分析器的執行狀況。
能夠定義數據導入處理器,從關係數據庫將數據導入 到Solr索引庫中。
經過此菜單能夠建立索引、更新索引、刪除索引等操做,界面以下:
/update表示更新索引,solr默認根據id(惟一約束)域來更新Document的內容,若是根據id值搜索不到id域則會執行添加操做,若是找到則更新。
經過/select執行搜索索引,必須指定「q」查詢條件方可搜索。
schema.xml,在SolrCore的conf目錄下,它是Solr數據表配置文件,它定義了加入索引的數據的數據類型。主要包括FieldTypes、Fields和其餘的一些缺省設置。
下邊「text_general」是Solr默認提供的FieldType,經過它說明FieldType定義的內容:
FieldType子結點包括:name,class,positionIncrementGap等一些參數:
name:是這個FieldType的名稱
class:是Solr提供的包solr.TextField,solr.TextField 容許用戶經過分析器來定製索引和查詢,分析器包括一個分詞器(tokenizer)和多個過濾器(filter)
positionIncrementGap:可選屬性,定義在同一個文檔中此類型數據的空白間隔,避免短語匹配錯誤,此值至關於Lucene的短語查詢設置slop值,根據經驗設置爲100。
例如:搜索big car,若是document中存的是big red car,就沒法搜索到了, positionIncrementGap就是設置big和car中間最大的間隔距離,只要在距離內就能搜索到.
在FieldType定義的時候最重要的就是定義這個類型的數據在創建索引和進行查詢的時候要使用的分析器analyzer,包括分詞和過濾
索引分析器中:使用solr.StandardTokenizerFactory標準分詞器,solr.StopFilterFactory停用詞過濾器,solr.LowerCaseFilterFactory小寫過濾器。
搜索分析器中:使用solr.StandardTokenizerFactory標準分詞器,solr.StopFilterFactory停用詞過濾器,這裏還用到了solr.SynonymFilterFactory同義詞過濾器。
solr索引字段在solrhome\collection1\conf\schema.xml配置文件中,相似下面這些,包含在<fields>與</fields>之間的。
在fields結點內定義具體的Field,filed定義包括name,type(爲以前定義過的各類FieldType),indexed(是否被索引),stored(是否被儲存),multiValued(是否存儲多個值)等屬性。
以下:
<field name="name" type="text_general" indexed="true" stored="true"/>
<field name="features" type="text_general" indexed="true" stored="true" multiValued="true"/>
multiValued:該Field若是要存儲多個值時設置爲true,solr容許一個Field存儲多個值,好比存儲一個用戶的好友id(多個),商品的圖片(多個,大圖和小圖),經過使用solr查詢要看出返回給客戶端是數組:
Solr中默認定義惟一主鍵key爲id域,以下:
Solr在刪除、更新索引時使用id域進行判斷,也能夠自定義惟一主鍵。
注意在建立索引時必須指定惟一約束。
copyField複製域,能夠將多個Field複製到一個Field中,以便進行統一的檢索:
好比,輸入關鍵字搜索title標題內容content,
定義title、content、text的域:
根據關鍵字只搜索text域的內容就至關於搜索title和content,將title和content複製到text中,以下:
動態字段就是不用指定具體的名稱,只要定義字段名稱的規則,例如定義一個 dynamicField,name 爲*_i,定義它的type爲text,那麼在使用這個字段的時候,任何以_i結尾的字段都被認爲是符合這個定義的,例如:name_i,gender_i,school_i等。
自定義Field名爲:product_title_t,「product_title_t」和scheam.xml中的dynamicField規則匹配成功,以下:
「product_title_t」是以「_t」結尾。
建立索引:
搜索索引:
使用IKAnalyzer中文分析器。
第一步:把IKAnalyzer2012FF_u1.jar添加到solr/WEB-INF/lib目錄下。
第二步:複製IKAnalyzer的配置文件和自定義詞典和停用詞詞典到solr的classpath下。
也就是在apache-tomcat-7.0.54\webapps\solr\WEB-INF目錄下新建classes目錄,將配置文件和詞典放進去.
第三步:在schema.xml中添加一個自定義的fieldType,使用中文分析器。
<!-- IKAnalyzer--> <fieldType name="text_ik" class="solr.TextField"> <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/> </fieldType> |
第四步:定義field,指定field的type屬性爲text_ik
<!--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"/> |
第四步:重啓tomcat
測試:
若是不使用Solr提供的Field能夠針對具體的業務須要自定義一套Field,以下是商品信息Field:
<!--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"/>
使用dataimport插件批量導入數據。
第一步:把dataimport插件依賴的jar包添加到solrcore(collection1\lib)中
還須要mysql的數據庫驅動。
第二步:配置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,保存到collection1\conf\目錄下
<?xml version="1.0" encoding="UTF-8" ?> <dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/lucene" 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
第五步:點擊「execute」按鈕導入數據
導入數據前會先清空索引庫,而後再導入。
刪除索引格式以下:
1) 刪除制定ID的索引
<delete> <id>8</id> </delete>
2) 刪除查詢到的索引數據
<delete> <query>product_catalog_name:幽默雜貨</query> </delete>
3) 刪除全部索引數據
<delete> <query>*:*</query> </delete>
經過/select搜索索引,Solr制定一些參數完成不一樣需求的搜索:
2. fq - (filter query)過慮查詢,做用:在q查詢符合結果中同時是fq查詢符合的,例如::
過濾查詢價格從1到20的記錄。
也能夠在「q」查詢條件中使用product_price:[1 TO 20],以下:
也可使用「*」表示無限,例如:
20以上:product_price:[20 TO *]
20如下:product_price:[* TO 20]
3. sort - 排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 。示例:
按價格降序
4. start - 分頁顯示使用,開始記錄下標,從0開始
5. rows - 指定返回結果最多有多少條記錄,配合start來實現分頁。
顯示前10條。
6. fl - 指定返回那些字段內容,用逗號或空格分隔多個。
顯示商品圖片、商品名稱、商品價格
7. df-指定一個搜索Field
也能夠在SolrCore目錄 中conf/solrconfig.xml文件中指定默認搜索Field,指定後就能夠直接在「q」查詢條件中輸入關鍵字。
8. wt - (writer type)指定輸出格式,能夠有 xml, json, php, phps, 後面 solr 1.3增長的,要用通知咱們,由於默認沒有打開。
9. hl 是否高亮 ,設置高亮Field,設置格式前綴和後綴。
solrj是訪問Solr服務的java客戶端,提供索引和搜索的請求方法,SolrJ一般在嵌入在業務系統中,經過SolrJ的API接口操做Solr服務,以下圖:
第一步:建立一個java工程
第二步:導入jar包。包括solrJ的jar包。還須要
第三步:使用SolrServer和Solr服務器創建鏈接。HttpSolrServer對象創建鏈接。SolrServer是抽象類,鏈接單機版solr使用httpSolrServer,連接集羣版使用CloudSolrServer。
第四步:建立一個SolrInputDocument對象,而後添加域。
第五步:將SolrInputDocument添加到索引庫。
第六步:提交。
1 //向索引庫中添加索引 2 3 @Test 4 5 public void addDocument() throws Exception { 6 7 //和solr服務器建立鏈接 8 9 //參數:solr服務器的地址 10 11 SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); 12 13 //建立一個文檔對象 14 15 SolrInputDocument document = new SolrInputDocument(); 16 17 //向文檔中添加域 18 19 //第一個參數:域的名稱,域的名稱必須是在schema.xml中定義的 20 21 //第二個參數:域的值 22 23 document.addField("id", "c0001"); 24 25 document.addField("title_ik", "使用solrJ添加的文檔"); 26 27 document.addField("content_ik", "文檔的內容"); 28 29 document.addField("product_name", "商品名稱"); 30 31 //把document對象添加到索引庫中 32 33 solrServer.add(document); 34 35 //提交修改 36 37 solrServer.commit(); 38 39 40 41 }
@Test public void testIndexCreate() throws Exception{ //建立和Solr服務端鏈接 SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); //建立solr文檔對象 SolrInputDocument doc = new SolrInputDocument(); //域要先定義後使用,還有注意必需要有id主鍵域 //solr中沒有專用的修改方法, 會自動根據id進行查找,若是找到了則刪除原來的將新的加入就是修改,若是沒找到,將新的直接加入則就是新增 doc.addField("id", "a001"); doc.addField("product_name", "檯燈1`111"); doc.addField("product_price", "12.5"); //將文檔加入solrServer對象中 solrServer.add(doc); //提交 solrServer.commit(); }
1 //刪除文檔,根據id刪除 2 3 @Test 4 5 public void deleteDocumentByid() throws Exception { 6 7 //建立鏈接 8 9 SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); 10 11 //根據id刪除文檔 12 13 solrServer.deleteById("c0001"); 14 15 //提交修改 16 17 solrServer.commit(); 18 19 }
查詢語法徹底支持Lucene的查詢語法。
1 //根據查詢條件刪除文檔 2 3 @Test 4 5 public void deleteDocumentByQuery() throws Exception { 6 7 //建立鏈接 8 9 SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); 10 11 //根據查詢條件刪除文檔,這裏是刪除全部*:* 12 13 solrServer.deleteByQuery("*:*"); 14 15 //提交修改 16 17 solrServer.commit(); 18 19 }
在solrJ中修改沒有對應的update方法,只有add方法,只須要添加一條新的文檔,和被修改的文檔id一致就,能夠修改了。本質上就是先刪除後添加。
1 //查詢索引 2 3 @Test 4 5 public void queryIndex() throws Exception { 6 7 //建立鏈接,連接solr服務端 8 9 SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); 10 11 //建立一個query對象,solr查詢條件對象 12 13 SolrQuery query = new SolrQuery(); 14 15 //設置查詢條件 16 17 query.setQuery("*:*"); 18 19 //查詢,執行查詢並獲取查詢響應對象 20 21 QueryResponse queryResponse = solrServer.query(query); 22 23 //取查詢結果,從查詢響應中獲取查詢結果集對象 24 25 SolrDocumentList solrDocumentList = queryResponse.getResults(); 26 27 //共查詢到商品數量 28 29 System.out.println("共查詢到商品數量:" + solrDocumentList.getNumFound()); 30 31 //遍歷查詢的結果 32 33 for (SolrDocument solrDocument : solrDocumentList) { 34 35 System.out.println(solrDocument.get("id")); 36 37 System.out.println(solrDocument.get("product_name")); 38 39 System.out.println(solrDocument.get("product_price")); 40 41 System.out.println(solrDocument.get("product_catalog_name")); 42 43 System.out.println(solrDocument.get("product_picture")); 44 45 46 47 } 48 49 }
其中包含查詢、過濾、分頁、排序、高亮顯示等處理。
例子1:
//複雜查詢索引 @Test public void queryIndex2() throws Exception { //建立鏈接 SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); //建立一個query對象 SolrQuery query = new SolrQuery(); //設置查詢條件 query.setQuery("鑽石"); //過濾條件 query.setFilterQueries("product_catalog_name:幽默雜貨"); //排序條件 query.setSort("product_price", ORDER.asc); //分頁處理 query.setStart(0); query.setRows(10); //結果中域的列表 query.setFields("id","product_name","product_price","product_catalog_name","product_picture"); //設置默認搜索域 query.set("df", "product_keywords"); //高亮顯示 query.setHighlight(true); //高亮顯示的域 query.addHighlightField("product_name"); //高亮顯示的前綴 query.setHighlightSimplePre("<em>"); //高亮顯示的後綴 query.setHighlightSimplePost("</em>"); //執行查詢 QueryResponse queryResponse = solrServer.query(query); //取查詢結果 SolrDocumentList solrDocumentList = queryResponse.getResults(); //共查詢到商品數量 System.out.println("共查詢到商品數量:" + solrDocumentList.getNumFound()); //遍歷查詢的結果 for (SolrDocument solrDocument : solrDocumentList) { System.out.println(solrDocument.get("id")); //取高亮顯示 String productName = ""; Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting(); List<String> list = highlighting.get(solrDocument.get("id")).get("product_name"); //判斷是否有高亮內容 if (null != list) { productName = list.get(0); } else { productName = (String) solrDocument.get("product_name"); } System.out.println(productName); System.out.println(solrDocument.get("product_price")); System.out.println(solrDocument.get("product_catalog_name")); System.out.println(solrDocument.get("product_picture")); } }
例子2
@Test public void testIndexSearch2() throws Exception{ //鏈接solr服務端 SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); //建立solr查詢條件對象 SolrQuery solrQuery = new SolrQuery(); //查詢關鍵字輸入 solrQuery.setQuery("檯燈"); //設置默認搜索域 solrQuery.set("df", "product_keywords"); //設置過濾查詢 solrQuery.addFilterQuery("product_price:[1 TO 100]"); //設置排序,這裏是降序 solrQuery.setSort("product_price", ORDER.desc); //=======設置分頁======== //設置起始條數 solrQuery.setStart(0); //設置查詢多少條 solrQuery.setRows(50); //========設置高亮顯示======= //高亮默認是關閉的,因此要手動開啓 solrQuery.setHighlight(true); //設置須要高亮顯示的域 solrQuery.addHighlightField("product_name"); //設置高亮前綴 solrQuery.setHighlightSimplePre("<span style=\"color:red\">"); //設置高亮後綴 solrQuery.setHighlightSimplePost("</span>"); //===================查詢並獲取查詢響應對象===================================== QueryResponse queryResponse = solrServer.query(solrQuery); //從查詢響應中獲取查詢結果集對象 SolrDocumentList results = queryResponse.getResults(); //打印一共查詢到多少條記錄,也就是記錄總數 System.out.println("=====count====" + results.getNumFound()); //遍歷查詢結果集 for(SolrDocument doc : results){ System.out.println("============="+doc.get("id")); //獲取高亮 Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting(); List<String> list = highlighting.get(doc.get("id")).get("product_name"); if(list != null && list.size() > 0){ String hlName = list.get(0); System.out.println("=======high lighting=====" + hlName); } System.out.println("============="+doc.get("product_name")); System.out.println("============="+doc.get("product_price")); System.out.println("===================================================="); } }
建立一個web工程導入jar包
一、springmvc的相關jar包
二、solrJ的jar包
三、Example\lib\ext下的jar包
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <context:component-scan base-package="com.itheima.jd"/> <!-- 配置註解驅動,若是配置此標籤能夠不用配置處理器映射器和適配器 --> <mvc:annotation-driven/> <!-- 配置視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!-- SolrServer的配置 --> <bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer"> <constructor-arg index="0" value="http://localhost:8080/solr"/> </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" 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>solr-jd</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> <!-- 配置前段控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <!-- 指定springmvc配置文件的路徑 若是不指定默認爲:/WEB-INF/${servlet-name}-servlet.xml --> <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> <!-- 解決post亂碼問題 --> <filter> <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
功能:接收service層傳遞過來的參數,根據參數查詢索引庫,返回查詢結果。
參數:SolrQuery對象
返回值:一個商品列表List<ProductModel>,還須要返回查詢結果的總數量。
返回:ResultModel
方法定義:ResultModel queryProduct(SolrQuery query) throws Exception;
商品對象模型:
public class ProductModel { // 商品編號 private String pid; // 商品名稱 private String name; // 商品分類名稱 private String catalog_name; // 價格 private float price; // 商品描述 private String description; // 圖片名稱 private String picture; }
返回值對象模型
public class ResultModel { // 商品列表 private List<ProductModel> productList; // 商品總數 private Long recordCount; // 總頁數 private int pageCount; // 當前頁 private int curPage; }
dao
@Repository public class ProductDaoImpl implements ProductDao { @Autowired private SolrServer solrServer; @Override public ResultModel queryProduct(SolrQuery query) throws Exception { ResultModel resultModel = new ResultModel(); //根據query對象查詢商品列表 QueryResponse queryResponse = solrServer.query(query); SolrDocumentList solrDocumentList = queryResponse.getResults(); //取查詢結果的總數量 resultModel.setRecordCount(solrDocumentList.getNumFound()); List<ProductModel> productList = new ArrayList<>(); //遍歷查詢結果 for (SolrDocument solrDocument : solrDocumentList) { //取商品信息 ProductModel productModel = new ProductModel(); productModel.setPid((String) solrDocument.get("id")); //取高亮顯示 String productName = ""; Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting(); List<String> list = highlighting.get(solrDocument.get("id")).get("product_name"); if (null != list) { productName = list.get(0); } else { productName = (String) solrDocument.get("product_name"); } productModel.setName(productName); if(null == doc.get("product_price")){ productModel.setPrice(0f); }else{ productModel.setPrice((float)doc.get("product_price")); } productModel.setCatalog_name((String) solrDocument.get("product_catalog_name")); productModel.setPicture((String) solrDocument.get("product_picture")); //添加到商品列表 productList.add(productModel); } //商品列表添加到resultmodel中 resultModel.setProductList(productList); return resultModel; } }
功能:接收action傳遞過來的參數,根據參數拼裝一個查詢條件,調用dao層方法,查詢商品列表。接收返回的商品列表和商品的總數量,根據每頁顯示的商品數量計算總頁數。
參數:
一、查詢條件:字符串
二、商品分類的過濾條件:商品的分類名稱,字符串
三、商品價格區間:傳遞一個字符串,知足格式:「0-100、101-200、201-*」
四、排序條件:頁面傳遞過來一個升序或者降序就能夠,默認是價格排序。0:升序1:降序
五、分頁信息:每頁顯示的記錄條數建立一個常量60條。傳遞一個當前頁碼就能夠了。
業務邏輯
一、根據參數建立查詢對象
二、調用dao執行查詢。
三、根據總記錄數計算總頁數。
返回值:ResultModel
方法定義:ResultModel queryProduct(String queryString, String caltalog_name, String price, String sort, Integer page) throws Exception;
@Service public class ProductServiceImpl implements ProductService { @Autowired private ProductDao productDao; @Override public ResultModel queryProduct(String queryString, String caltalog_name, String price, String sort, Integer page) throws Exception { //拼裝查詢條件 SolrQuery query = new SolrQuery(); //查詢條件 if (null != queryString && !"".equals(queryString)) { query.setQuery(queryString); } else { query.setQuery("*:*"); } //商品分類名稱過濾 if (null != caltalog_name && !"".equals(caltalog_name)) { query.addFilterQuery("product_catalog_name:" + caltalog_name); } //價格區間過濾 if (null != price && !"".equals(price)) { String[] strings = price.split("-"); query.addFilterQuery("product_price:["+strings[0]+" TO "+strings[1]+"]"); } //排序條件 if ("1".equals(sort)) { query.setSort("product_price", ORDER.desc); } else { query.setSort("product_price", ORDER.asc); } //分頁處理 if (null == page) { page = 1; } //start int start = (page-1) * Commons.PAGE_SIZE; query.setStart(start); query.setRows(Commons.PAGE_SIZE); //設置默認搜索域 query.set("df", "product_keywords"); //高亮設置 query.setHighlight(true); query.addHighlightField("product_name"); query.setHighlightSimplePre("<span style=\"color:red\">"); query.setHighlightSimplePost("</span>"); //查詢商品列表 ResultModel resultModel = productDao.queryProduct(query); //計算總頁數 long recordCount = resultModel.getRecordCount(); int pages = (int) (recordCount/Commons.PAGE_SIZE); if (recordCount % Commons.PAGE_SIZE > 0) { pages ++; } resultModel.setPageCount(pages); resultModel.setCurPage(page); return resultModel; } }
功能:接收頁面傳遞過來的參數調用service查詢商品列表。將查詢結果返回給jsp頁面,還須要查詢參數的回顯。
參數:
一、查詢條件:字符串
二、商品分類的過濾條件:商品的分類名稱,字符串
三、商品價格區間:傳遞一個字符串,知足格式:「0-100、101-200、201-*」
四、排序條件:頁面傳遞過來一個升序或者降序就能夠,默認是價格排序。0:升序1:降序
五、分頁信息:每頁顯示的記錄條數建立一個常量60條。傳遞一個當前頁碼就能夠了。
六、Model:至關於request。
返回結果:String類型,就是一個jsp的名稱。
方法定義:String queryProduct(String queryString, String caltalog_name, String price, String sort, Integer page, Model model) throws Exception;
@Controller public class ProductAction { @Autowired private ProductService productService; @RequestMapping("/list") public String queryProduct(String queryString, String catalog_name, String price, String sort, Integer page, Model model) throws Exception { //查詢商品列表 ResultModel resultModel = productService.queryProduct(queryString, catalog_name, price, sort, page); //列表傳遞給jsp model.addAttribute("result", resultModel); //參數回顯 model.addAttribute("queryString", queryString); model.addAttribute("caltalog_name", catalog_name); model.addAttribute("price", price); model.addAttribute("sort", sort); model.addAttribute("page", page); return "product_list"; } }