private void BindSearch() { queryErrorOccurred = false; mojoPortal.SearchIndex.IndexItemCollection searchResults = mojoPortal.SearchIndex.IndexHelper.Search( siteSettings.SiteId, isSiteEditor, GetUserRoles(), config.GetFeatureGuids(), modifiedBeginDate, modifiedEndDate, txtSearch.Text, WebConfigSettings.EnableSearchResultsHighlighting, WebConfigSettings.SearchResultsFragmentSize, pageNumber, pageSize, WebConfigSettings.SearchMaxClauseCount, out totalHits, out queryErrorOccurred); totalPages = 1; if (pageSize > 0) { totalPages = totalHits / pageSize; } if (totalHits <= pageSize) { totalPages = 1; } else { int remainder; Math.DivRem(totalHits, pageSize, out remainder); if (remainder > 0) { totalPages += 1; } } pgr.ShowFirstLast = true; pgr.PageSize = pageSize; pgr.PageCount = totalPages; pgr.Visible = (totalPages > 1); rptResults.DataSource = searchResults; rptResults.DataBind(); updPnl.Update(); }
public static IndexItemCollection Search( int siteId, bool isAdminContentAdminOrSiteEditor, List<string> userRoles, Guid[] featureGuids, DateTime modifiedBeginDate, DateTime modifiedEndDate, string queryText, bool highlightResults, int highlightedFragmentSize, int pageNumber, int pageSize, int maxClauseCount, out int totalHits, out bool invalidQuery) { invalidQuery = false; totalHits = 0; IndexItemCollection results = new IndexItemCollection(); if (string.IsNullOrEmpty(queryText)) { return results; } using (Lucene.Net.Store.Directory searchDirectory = GetDirectory(siteId)) { if (!IndexReader.IndexExists(searchDirectory)) { return results; } long startTicks = DateTime.Now.Ticks; try { if (maxClauseCount != 1024) { BooleanQuery.MaxClauseCount = maxClauseCount; } // there are different analyzers for different languages // see LuceneSettings.config in the root of the web LuceneSettingsProvider provider = LuceneSettingsManager.Providers[GetSiteProviderName(siteId)]; Analyzer analyzer = provider.GetAnalyzer(); Query searchQuery = MultiFieldQueryParser.Parse( Lucene.Net.Util.Version.LUCENE_30, new string[] { queryText, queryText, queryText, queryText, queryText, queryText.Replace("*", string.Empty) }, new string[] { "Title", "ModuleTitle", "contents", "PageName", "PageMetaDesc", "Keyword" }, analyzer); BooleanQuery filterQuery = new BooleanQuery(); // won't be used to score the results if (!isAdminContentAdminOrSiteEditor) // skip role filters for these users { AddRoleFilters(userRoles, filterQuery); AddModuleRoleFilters(userRoles, filterQuery); } TermRangeQuery beginDateFilter = new TermRangeQuery( "PublishBeginDate", DateTime.MinValue.ToString("s"), DateTime.UtcNow.ToString("s"), true, true); filterQuery.Add(beginDateFilter, Occur.MUST); TermRangeQuery endDateFilter = new TermRangeQuery( "PublishEndDate", DateTime.UtcNow.ToString("s"), DateTime.MaxValue.ToString("s"), true, true); filterQuery.Add(endDateFilter, Occur.MUST); if ((modifiedBeginDate.Date > DateTime.MinValue.Date) || (modifiedEndDate.Date < DateTime.MaxValue.Date)) { TermRangeQuery lastModifiedDateFilter = new TermRangeQuery( "LastModUtc", modifiedBeginDate.Date.ToString("s"), modifiedEndDate.Date.ToString("s"), true, true); filterQuery.Add(lastModifiedDateFilter, Occur.MUST); } //if ((!DisableSearchFeatureFilters) && (featureGuid != Guid.Empty)) //{ // BooleanQuery featureFilter = new BooleanQuery(); // featureFilter.Add(new TermQuery(new Term("FeatureId", featureGuid.ToString())), Occur.MUST); // filterQuery.Add(featureFilter, Occur.MUST); //} if ((featureGuids != null) && (featureGuids.Length > 0)) { BooleanQuery featureFilter = new BooleanQuery(); foreach (Guid featureGuid in featureGuids) { featureFilter.Add(new TermQuery(new Term("FeatureId", featureGuid.ToString())), Occur.SHOULD); } filterQuery.Add(featureFilter, Occur.MUST); } Filter filter = new QueryWrapperFilter(filterQuery); // filterQuery won't affect result scores using (IndexSearcher searcher = new IndexSearcher(searchDirectory)) { //http://stackoverflow.com/questions/9872933/migrating-lucene-hitcollector-2-x-to-collector-3-x //TopScoreDocCollector collector = TopScoreDocCollector.Create(maxResults, true); int maxResults = int.MaxValue; TopDocs hits = searcher.Search(searchQuery, filter, maxResults); int startHit = 0; if (pageNumber > 1) { startHit = ((pageNumber - 1) * pageSize); } totalHits = hits.TotalHits; int end = startHit + pageSize; if (totalHits <= end) { end = totalHits; } int itemsAdded = 0; int itemsToAdd = end; QueryScorer scorer = new QueryScorer(searchQuery); SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span class='searchterm'>", "</span>"); Highlighter highlighter = new Highlighter(formatter, scorer); highlighter.TextFragmenter = new SimpleFragmenter(highlightedFragmentSize); for (int i = startHit; i < itemsToAdd; i++) { Document doc = searcher.Doc(hits.ScoreDocs[i].Doc); IndexItem indexItem = new IndexItem(doc, hits.ScoreDocs[i].Score); if (highlightResults) { try { TokenStream stream = analyzer.TokenStream("contents", new StringReader(doc.Get("contents"))); string highlightedResult = highlighter.GetBestFragment(stream, doc.Get("contents")); if (highlightedResult != null) { indexItem.Intro = highlightedResult; } } catch (NullReferenceException) { } } results.Add(indexItem); itemsAdded += 1; } results.ItemCount = itemsAdded; results.PageIndex = pageNumber; results.ExecutionTime = DateTime.Now.Ticks - startTicks; } } catch (ParseException ex) { invalidQuery = true; log.Error("handled error for search terms " + queryText, ex); // these parser exceptions are generally caused by // spambots posting too much junk into the search form // heres an option to automatically ban the ip address HandleSpam(queryText, ex); return results; } catch (BooleanQuery.TooManyClauses ex) { invalidQuery = true; log.Error("handled error for search terms " + queryText, ex); return results; } catch (System.IO.IOException ex) { invalidQuery = true; log.Error("handled error for search terms " + queryText, ex); return results; } return results; } }
public static IndexItemCollection Browse( int siteId, Guid featureGuid, DateTime modifiedBeginDate, DateTime modifiedEndDate, int pageNumber, int pageSize, out int totalHits) { totalHits = 0; IndexItemCollection results = new IndexItemCollection(); using (Lucene.Net.Store.Directory searchDirectory = GetDirectory(siteId)) { Filter filter = null; BooleanQuery filterQuery = null; if ((modifiedBeginDate.Date > DateTime.MinValue.Date) || (modifiedEndDate.Date < DateTime.MaxValue.Date)) { filterQuery = new BooleanQuery(); // won't be used to score the results TermRangeQuery lastModifiedDateFilter = new TermRangeQuery( "LastModUtc", modifiedBeginDate.Date.ToString("s"), modifiedEndDate.Date.ToString("s"), true, true); filterQuery.Add(lastModifiedDateFilter, Occur.MUST); } if (featureGuid != Guid.Empty) { if (filterQuery == null) { filterQuery = new BooleanQuery(); } BooleanQuery featureFilter = new BooleanQuery(); featureFilter.Add(new TermQuery(new Term("FeatureId", featureGuid.ToString())), Occur.MUST); filterQuery.Add(featureFilter, Occur.MUST); } if (filterQuery != null) { filter = new QueryWrapperFilter(filterQuery); // filterQuery won't affect result scores } MatchAllDocsQuery matchAllQuery = new MatchAllDocsQuery(); using (IndexSearcher searcher = new IndexSearcher(searchDirectory)) { int maxResults = int.MaxValue; TopDocs hits = searcher.Search(matchAllQuery, filter, maxResults); int startHit = 0; if (pageNumber > 1) { startHit = ((pageNumber - 1) * pageSize); } totalHits = hits.TotalHits; if (startHit > totalHits) { startHit = totalHits; } int end = startHit + pageSize; if (totalHits <= end) { end = totalHits; } int itemsAdded = 0; int itemsToAdd = end; for (int i = startHit; i < itemsToAdd; i++) { Document doc = searcher.Doc(hits.ScoreDocs[i].Doc); IndexItem indexItem = new IndexItem(doc, hits.ScoreDocs[i].Score); results.Add(indexItem); itemsAdded += 1; } results.ItemCount = itemsAdded; results.PageIndex = pageNumber; results.ExecutionTime = DateTime.Now.Ticks; // -0; } // using (IndexReader reader = IndexReader.Open(searchDirectory, false)) // { // totalHits = reader.NumDocs(); // int startHit = 0; // int itemsToAdd = pageSize; // if (pageNumber > 1) // { // startHit = ((pageNumber - 1) * pageSize); // int end = startHit + pageSize; // if (totalHits <= end) // { // end = totalHits; // } // itemsToAdd = end; // } // for (int i = startHit; i < itemsToAdd; i++) // { // Document doc = reader.Document(i); // IndexItem indexItem = new IndexItem(doc, 1); // results.Add(indexItem); // } // } } return results; }
private void DoSearch(HttpContext context) { // this is only to make sure its initialized // before indexing is queued on a thread // because there is no HttpContext on // external threads and httpcontext is needed to initilaize // once initialized its cached IndexBuilderProviderCollection indexProviders = IndexBuilderManager.Providers; searchResults = mojoPortal.SearchIndex.IndexHelper.Search( siteSettings.SiteId, isSiteEditor, GetUserRoles(context), featureGuid, modifiedBeginDate, modifiedEndDate, query, false, WebConfigSettings.SearchResultsFragmentSize, pageNumber, pageSize, WebConfigSettings.SearchMaxClauseCount, out totalHits, out queryErrorOccurred); start = 1; if (pageNumber > 1) { start = ((pageNumber - 1) * pageSize) + 1; } end = pageSize; if (start > 1) { end += start; } if (end > totalHits) { end = totalHits; } totalPages = 1; int pageLowerBound = (pageSize * pageNumber) - pageSize; if (pageSize > 0) { totalPages = totalHits / pageSize; } if (totalHits <= pageSize) { totalPages = 1; } else { int remainder; Math.DivRem(totalHits, pageSize, out remainder); if (remainder > 0) { totalPages += 1; } } }
private void RenderSearchResults(HttpContext context, mojoPortal.SearchIndex.IndexItemCollection searchResults) { context.Response.ContentType = "application/xml"; Encoding encoding = new UTF8Encoding(); context.Response.ContentEncoding = encoding; string sanitizedQuery = SecurityHelper.RemoveMarkup(query); using (XmlTextWriter xmlTextWriter = new XmlTextWriter(context.Response.OutputStream, encoding)) { xmlTextWriter.Formatting = Formatting.Indented; xmlTextWriter.WriteStartDocument(); xmlTextWriter.WriteStartElement("feed"); xmlTextWriter.WriteAttributeString("xmlns", "http://www.w3.org/2005/Atom"); xmlTextWriter.WriteAttributeString("xmlns:opensearch", "http://a9.com/-/spec/opensearch/1.1/"); xmlTextWriter.WriteStartElement("title"); xmlTextWriter.WriteValue(string.Format(CultureInfo.InvariantCulture, Resource.SearchTitleFormat, siteSettings.SiteName, sanitizedQuery)); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("link"); xmlTextWriter.WriteAttributeString("href", SiteRoot + "/SearchResults.ashx?q=" + context.Server.UrlEncode(sanitizedQuery)); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("updated"); xmlTextWriter.WriteValue(DateTime.UtcNow.ToString("u", CultureInfo.InvariantCulture).Replace(" ", "T")); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("author"); xmlTextWriter.WriteStartElement("name"); xmlTextWriter.WriteValue(siteSettings.CompanyName); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("id"); xmlTextWriter.WriteValue("urn:uuid:" + siteSettings.SiteGuid.ToString()); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("opensearch:totalResults"); xmlTextWriter.WriteValue(totalHits.ToString(CultureInfo.InvariantCulture)); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("opensearch:startIndex"); xmlTextWriter.WriteValue(start.ToString(CultureInfo.InvariantCulture)); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("opensearch:itemsPerPage"); xmlTextWriter.WriteValue(pageSize.ToString(CultureInfo.InvariantCulture)); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("opensearch:Query"); xmlTextWriter.WriteAttributeString("role", "request"); xmlTextWriter.WriteAttributeString("searchTerms", sanitizedQuery); xmlTextWriter.WriteAttributeString("startPage", "1"); xmlTextWriter.WriteEndElement(); //this is a link to the xhtml search page xmlTextWriter.WriteStartElement("link"); xmlTextWriter.WriteAttributeString("rel", "alternate"); xmlTextWriter.WriteAttributeString("href", SiteRoot + "/SearchResults.aspx?q=" + context.Server.UrlEncode(sanitizedQuery) + "&p=" + pageNumber.ToString(CultureInfo.InvariantCulture)); xmlTextWriter.WriteAttributeString("type", "text/html"); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("link"); xmlTextWriter.WriteAttributeString("rel", "self"); xmlTextWriter.WriteAttributeString("href", SiteRoot + "/SearchResults.ashx?q=" + context.Server.UrlEncode(sanitizedQuery) + "&p=" + pageNumber.ToString(CultureInfo.InvariantCulture)); xmlTextWriter.WriteAttributeString("type", "application/atom+xml"); xmlTextWriter.WriteEndElement(); if (totalPages > 1) { xmlTextWriter.WriteStartElement("link"); xmlTextWriter.WriteAttributeString("rel", "first"); xmlTextWriter.WriteAttributeString("href", SiteRoot + "/SearchResults.ashx?q=" + context.Server.UrlEncode(sanitizedQuery) + "&p=1"); xmlTextWriter.WriteAttributeString("type", "application/atom+xml"); xmlTextWriter.WriteEndElement(); if (pageNumber > 1) { xmlTextWriter.WriteStartElement("link"); xmlTextWriter.WriteAttributeString("rel", "previous"); xmlTextWriter.WriteAttributeString("href", SiteRoot + "/SearchResults.ashx?q=" + context.Server.UrlEncode(sanitizedQuery) + "&p=" + (pageNumber - 1).ToString(CultureInfo.InvariantCulture)); xmlTextWriter.WriteAttributeString("type", "application/atom+xml"); xmlTextWriter.WriteEndElement(); } if (pageNumber < totalPages) { xmlTextWriter.WriteStartElement("link"); xmlTextWriter.WriteAttributeString("rel", "next"); xmlTextWriter.WriteAttributeString("href", SiteRoot + "/SearchResults.ashx?q=" + context.Server.UrlEncode(sanitizedQuery) + "&p=" + (pageNumber + 1).ToString(CultureInfo.InvariantCulture)); xmlTextWriter.WriteAttributeString("type", "application/atom+xml"); xmlTextWriter.WriteEndElement(); } xmlTextWriter.WriteStartElement("link"); xmlTextWriter.WriteAttributeString("rel", "last"); xmlTextWriter.WriteAttributeString("href", SiteRoot + "/SearchResults.ashx?q=" + context.Server.UrlEncode(sanitizedQuery) + "&p=" + totalPages.ToString(CultureInfo.InvariantCulture)); xmlTextWriter.WriteAttributeString("type", "application/atom+xml"); xmlTextWriter.WriteEndElement(); } ////this is a link to the description xmlTextWriter.WriteStartElement("link"); xmlTextWriter.WriteAttributeString("rel", "search"); xmlTextWriter.WriteAttributeString("type", "application/opensearchdescription+xml"); xmlTextWriter.WriteAttributeString("href", SiteRoot + "/SearchEngineInfo.ashx"); xmlTextWriter.WriteEndElement(); foreach (mojoPortal.SearchIndex.IndexItem item in searchResults) { xmlTextWriter.WriteStartElement("entry"); xmlTextWriter.WriteStartElement("link"); xmlTextWriter.WriteValue(BuildUrl(item)); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement("id"); xmlTextWriter.WriteValue(BuildUrl(item)); xmlTextWriter.WriteEndElement(); //xmlTextWriter.WriteRaw("<updated>2003-12-13T18:30:02Z</updated>"); xmlTextWriter.WriteStartElement("content"); xmlTextWriter.WriteAttributeString("type", "text"); xmlTextWriter.WriteCData(item.Intro); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteEndElement(); } xmlTextWriter.WriteEndElement(); } }
private void DoSearch() { if (Page.IsPostBack) { return; } if (Request.QueryString.Get("q") == null) { return; } query = Request.QueryString.Get("q"); if (this.query.Length == 0) { return; } //txtSearchInput.Text = Server.HtmlEncode(query).Replace(""", "\"") ; txtSearchInput.Text = SecurityHelper.SanitizeHtml(query); // this is only to make sure its initialized // before indexing is queued on a thread // because there is no HttpContext on // external threads and httpcontext is needed to initilaize // once initialized its cached IndexBuilderProviderCollection indexProviders = IndexBuilderManager.Providers; queryErrorOccurred = false; mojoPortal.SearchIndex.IndexItemCollection searchResults = mojoPortal.SearchIndex.IndexHelper.Search( siteSettings.SiteId, isSiteEditor, GetUserRoles(), featureGuid, modifiedBeginDate, modifiedEndDate, query, WebConfigSettings.EnableSearchResultsHighlighting, WebConfigSettings.SearchResultsFragmentSize, pageNumber, pageSize, WebConfigSettings.SearchMaxClauseCount, out totalHits, out queryErrorOccurred); if (searchResults.Count == 0) { ShowNoResults(); InitIndexIfNeeded(); return; } int start = 1; if (pageNumber > 1) { start = ((pageNumber - 1) * pageSize) + 1; } int end = pageSize; if (start > 1) { end += start; } if (end > totalHits) { end = totalHits; } this.pnlSearchResults.Visible = true; this.pnlNoResults.Visible = false; this.lblDuration.Visible = true; this.lblSeconds.Visible = true; this.lblFrom.Text = (start).ToString(); this.lblTo.Text = end.ToString(CultureInfo.InvariantCulture); this.lblTotal.Text = totalHits.ToString(CultureInfo.InvariantCulture); this.lblQueryText.Text = Server.HtmlEncode(query); float duration = searchResults.ExecutionTime * 0.0000001F; this.lblDuration.Text = duration.ToString(); divResults.Visible = true; totalPages = 1; //int pageLowerBound = (pageSize * pageNumber) - pageSize; if (pageSize > 0) { totalPages = totalHits / pageSize; } if (totalHits <= pageSize) { totalPages = 1; } else { int remainder; Math.DivRem(totalHits, pageSize, out remainder); if (remainder > 0) { totalPages += 1; } } //totalPages always seems 1 more than it should be not sure why //if (totalPages > 1) { totalPages -= 1; } string searchUrl = SiteRoot + "/SearchResults.aspx?q=" + Server.UrlEncode(query) + "&p={0}" + GetModBeginDateParam(true) + GetModEndDateParam(true) + GetFeatureParam(true); pgrTop.PageURLFormat = searchUrl; pgrTop.ShowFirstLast = true; pgrTop.CurrentIndex = pageNumber; pgrTop.PageSize = pageSize; pgrTop.PageCount = totalPages; pgrTop.Visible = (totalPages > 1); pgrBottom.PageURLFormat = searchUrl; pgrBottom.ShowFirstLast = true; pgrBottom.CurrentIndex = pageNumber; pgrBottom.PageSize = pageSize; pgrBottom.PageCount = totalPages; pgrBottom.Visible = (totalPages > 1); this.rptResults.DataSource = searchResults; this.rptResults.DataBind(); }