很久沒有寫關於umbraco的博客了,這段時間在研究solis search,感受它太強大,好東西是須要分享的,因此寫一篇簡單的使用博客分享給我的umbraco愛好者。javascript
在瞭解solis search以前,咱們須要簡單的瞭解apache solr, Apache Solr 是一個開源的搜索服務器。Solr 使用 Java 語言開發,主要基於 HTTP 和 Apache Lucene 實現。Lucene是一套用於全文檢索和搜尋的開源程式庫,由Apache軟件基金會支持和提供。Lucene提供了一個簡單卻強大的應用程式接口,可以作全文索引和搜尋。更詳細的介紹請充分利用搜索引擎,這裏就不作詳細介紹了。html
solis search就是基於apache solr開發的一個umbraco的插件。它在作了簡單的配置以後,就能夠檢索到umbraco content裏面的幾乎全部的文字內容,包括上傳的文檔或者選擇的media picker中的文檔(word, pdf, excel 等等)。java
安裝java環境是爲了運行apache solr server.apache
下載地址:http://www.java.com/zh_CN/,服務器
下載後安裝,安裝以後請配置環境變量,是java命令能夠直接在命令行根目錄運行。如何配置環境變量在這就不介紹了。app
下載地址:http://lucene.apache.org/solr/,這裏記住,必定要下載4.5.1版本的,否則使用會出現未知的錯誤。由於solis search是基於version 4.5開發的。ide
請參考官方文檔進行安裝:http://lucene.apache.org/solr/4_5_1/tutorial.html,ui
操做簡要說明:this
下載:https://www.solissearch.com/download/ 搜索引擎
推薦下載Solis Search 1.1.15.218 Umbraco package, 下載以後再umbraco後臺進行安裝
安裝過程通常不會出錯,若是出了錯,請下載手動安裝包,根據文檔進行安裝: https://www.solissearch.com/documentation/
安裝以後,找到安裝包裏面的schema.xml和solrconfig.xml而後 複製到solr的文件夾solr-4.5.1\example\solr\collection1\conf\下面,這一步很重要,而後重啓solr server: java -jar start.jar
接着就是rebuild index:
固然在rebuild index以前要根據具體的須要修改配置文件。
在這裏,我將個人配置貼出來,而且作簡單的介紹,
1 <?xml version="1.0"?> 2 <SolisSearch> 3 <SolrServer address="http://localhost:8983/solr" username="" licenseKey="" /> 4 <SearchSettings defaultField="text" enableLanguageSupport="true" enabledLanguages="en" highlight="true" highlightFields="text" fragmenter="regex" fragsize="300" defaultOperator="AND" /> 5 <Languages> 6 <Language name="en" rootNode="1064" /> 7 </Languages> 8 <DocTypes> 9 <DocType name="default" addPageNameToContent="true"> 10 <Properties> 11 <Property name="p1" property="Name" type="text" content="true" /> 12 <Property name="r1" property="relatedLinks" type="relatedLinks" parser="SolisSearch.Parsers.RelatedLinksParser,SolisSearch" /> 13 </Properties> 14 </DocType> 15 <DocType name="umbHomePage"> 16 <Properties> 17 <Property name="p1" property="mainHeading" type="text" content="true" /> 18 <Property name="p2" property="mainContent" type="text" content="true" striphtml="true"/> 19 </Properties> 20 </DocType> 21 <DocType name="newsGroup" addPageNameToContent="true"> 22 <Properties> 23 <Property name="p1" property="Name" type="text" content="true" /> 24 </Properties> 25 </DocType> 26 <DocType name="newsItem" addPageNameToContent="true"> 27 <Properties> 28 <Property name="p1" property="title" type="text" content="true" /> 29 <Property name="p2" property="content" type="text" content="true" striphtml="true"/> 30 <Property name="p3" property="downloadFile" type="relatedLinks" parser="SolisSearch.Parsers.RelatedLinksParser,SolisSearch" /> 31 <Property name="p4" property="uploadDoc" type="relatedLinks" parser="SolisSearch.Parsers.RelatedLinksParser,SolisSearch" /> 32 </Properties> 33 </DocType> 34 </DocTypes> 35 <Facets> 36 <Facet type="value" field="doctypes" mincount="0" sort="false" /> 37 <Facet type="range" field="last_modified" mincount="1"> 38 <Ranges> 39 <FacetRange name="date3" dynamic="thisday" dataType="date" /> 40 <FacetRange name="date4" dynamic="thisweek" dataType="date" /> 41 <FacetRange name="date5" dynamic="thismonth" dataType="date" /> 42 <FacetRange name="date6" dynamic="thisyear" dataType="date" /> 43 <FacetRange name="date7" dynamic="last" gap="20" dataType="date" /> 44 </Ranges> 45 </Facet> 46 </Facets> 47 </SolisSearch>
SolrServer:配置solr server的 地址,用戶名以及license key.
SearchSettings: 配置當前search的環境,支持的語言,連接操做符,是否高亮等等
DocTypes:這個是重點,用來配置能夠搜索出來的content字段
1 <DocType name="newsItem" addPageNameToContent="true"> 2 <Properties> 3 <Property name="p1" property="title" type="text" content="true" /> 4 <Property name="p2" property="content" type="text" content="true" striphtml="true"/> 5 <Property name="p3" property="downloadFile" type="relatedLinks" parser="SolisSearch.Parsers.RelatedLinksParser,SolisSearch" /> 6 <Property name="p4" property="uploadDoc" type="relatedLinks" parser="SolisSearch.Parsers.RelatedLinksParser,SolisSearch" /> 7 </Properties> 8 </DocType>
name="newsItem": 將名爲newsItem的document type添加到可搜索列表;
addPageNameToContent="true": 表示該document type的name是可搜索的;
Properties: 指定該document type中哪些property是能夠被搜索的;
Property: name - 標示符, property - 屬性名, type - 搜索的類型, content - 搜索的是內容值
type="relatedLinks": 表示使用solis search的方法去搜索,通常用來搜索word文檔,pdf文檔中的內容, 須要添加 parser="SolisSearch.Parsers.RelatedLinksParser,SolisSearch".
這裏的p3和p4表示添加了media picker類型以及upload的類型的屬性是能夠搜索的。
搜索view代碼:
1 @using System.Activities.Statements 2 @using System.Globalization 3 @using SolisSearch.Helpers 4 @using SolisSearch.Repositories 5 @inherits Umbraco.Web.Macros.PartialViewMacroPage 6 7 @{ 8 Layout = "../Master.cshtml"; 9 } 10 11 12 <h1>@ViewBag.Title</h1> 13 <h3>@ViewData["content"]</h3> 14 15 @{ 16 var query = HttpUtility.UrlDecode(Request.QueryString["q"]); 17 var fq = new List<string>(); 18 19 20 <script type="text/javascript"> 21 $(document).ready(function () { 22 23 $("#txtSearch").keydown(function (e) { 24 if (e.which == "13") { 25 $("#searchform").submit(); 26 } 27 }); 28 29 $(".facetlink").click(function () { 30 var filter = $(this).attr("data-filter"); 31 $("#filters").append("<input name='fq' type='hidden' value='" + filter + "¤' >"); 32 $("#searchform").submit(); 33 34 }); 35 36 $("#filters").on("click", "a", function () { 37 $(this).prev("input").remove(); 38 $("#searchform").submit(); 39 }); 40 }); 41 </script> 42 43 <div class="searchform"> 44 <form id="searchform" method="GET"> 45 <input id="txtSearch" autocomplete="off" type="search" name="q" value="@query" /> 46 <button type="submit">Search</button> 47 48 @if (!String.IsNullOrEmpty(Request["fq"])) 49 { 50 fq.AddRange(Request["fq"].TrimEnd(Convert.ToChar("¤")).Split(new[] { "¤," }, StringSplitOptions.RemoveEmptyEntries)); 51 } 52 53 <div id="filters"> 54 @{ 55 if (fq.Any()) 56 { 57 <h6>Active filters <span>(Click to remove)</span></h6> 58 foreach (var field in fq) 59 { 60 <input name="fq" type="hidden" value="@string.Format("{0}¤", field)" /> 61 <a href="#">@Html.Raw(GetFriendlyCategoryName(RangeFormatHelper.FormatRange(field))) <i class="fa fa-times"></i></a> 62 } 63 64 } 65 } 66 67 </div> 68 </form> 69 </div> 70 71 72 if (!String.IsNullOrEmpty(query) || fq.Any()) 73 { 74 var languageName = CultureInfo.CurrentCulture.TwoLetterISOLanguageName; 75 76 var searchRepo = new SearchRepository(); 77 var searchResultItems = searchRepo.SearchIndex(query, fq.ToArray(), 1, 0, null); 78 79 if (searchResultItems.SpellChecking.Any()) 80 { 81 <div class="spellchecking"> 82 <h4>Did you mean</h4> 83 @foreach (var spellitem in searchResultItems.SpellChecking) 84 { 85 86 foreach (var suggestion in spellitem.Suggestions) 87 { 88 <p><a href="?q=@suggestion">@suggestion</a></p> 89 } 90 91 } 92 </div> 93 } 94 95 <div class="facets"> 96 <div> 97 @if (searchResultItems.FacetFields.Any()) 98 { 99 var doctypesFacets = searchResultItems.FacetFields["doctypes"]; 100 <h4>Category</h4> 101 <ul> 102 @{ 103 foreach (var keyValuePair in doctypesFacets) 104 { 105 var friendlyname = GetFriendlyCategoryName(keyValuePair.Key); 106 if (String.IsNullOrEmpty(friendlyname)) 107 { 108 continue; 109 } 110 111 <li> 112 <a class="facetlink" data-filter="@Html.Raw(string.Format("{0}:{1}", "doctypes", keyValuePair.Key))" href="javascript:void(0);"> 113 @Html.Raw(friendlyname + " (" + keyValuePair.Value + ")") 114 </a> 115 </li> 116 } 117 } 118 119 </ul> 120 121 122 } 123 </div> 124 <div> 125 @if (searchResultItems.FacetQueries.Any()) 126 { 127 <h4>Date modified</h4> 128 <ul> 129 @foreach (var facetqueries in searchResultItems.FacetQueries) 130 { 131 <li> 132 <a class="facetlink" data-filter="@facetqueries.Key" data-value="@facetqueries.Key" href="javascript:void(0);"> 133 @Html.Raw(RangeFormatHelper.FormatRange(facetqueries.Key) + " (" + facetqueries.Value + ")") 134 </a> 135 </li> 136 } 137 </ul> 138 } 139 </div> 140 141 </div> 142 143 if (searchResultItems.Any()) 144 { 145 <div class="searchResults"> 146 <p>@string.Format("Total of {0} items found", searchResultItems.NumFound)</p> 147 <ol> 148 @foreach (var searchitem in searchResultItems) 149 { 150 <li> 151 <h4><a href="@Html.Raw(searchitem.LinkUrl ?? searchitem.ResourceName)">@Html.Raw(searchitem.Name ?? searchitem.DocumentTitle.FirstOrDefault() ?? Path.GetFileNameWithoutExtension(searchitem.ResourceName))</a></h4> 152 @{ 153 var highlightedSnippets = searchResultItems.Highlights[searchitem.Id]; 154 if (highlightedSnippets != null && highlightedSnippets.Any()) 155 { 156 foreach (var highlightItem in highlightedSnippets) 157 { 158 @Html.Raw(string.Join(" ", highlightItem.Value)) 159 } 160 } 161 else 162 { 163 var contentString = string.Join(" ", searchitem.Content); 164 @Html.Raw(contentString.Substring(0, Math.Min(contentString.Length, 175))) 165 } 166 } 167 </li> 168 } 169 </ol> 170 </div> 171 172 } 173 else 174 { 175 <p style="clear: both;">No search results</p> 176 } 177 } 178 } 179 180 @functions 181 { 182 183 private string GetFriendlyCategoryName(string doctype) 184 { 185 if (doctype.Contains("/")) return doctype; 186 switch (doctype) 187 { 188 case "newsItem": 189 return "News Item"; 190 case "umbHomePage": 191 return "Article"; 192 default: 193 return "Others"; 194 195 } 196 } 197 198 }
作了如上操做後,就能夠開始使用solis search進行操做了。
有錯誤的地方,歡迎指出。
參考:
http://baike.baidu.com/view/5649738.htm?fr=aladdin
http://baike.baidu.com/view/371811.htm
尊重原創,轉載請說明出處!