/// <summary> /// Creates a new instance of the <see cref="T:SearchResultRow" /> class. /// </summary> /// <param name="result">The result to use.</param> /// <returns>The instance.</returns> public static SearchResultRow CreateInstance(SearchResult result) { string queryStringKeywords = "HL=" + GetKeywordsForQueryString(result.Matches); if(result.Document.TypeTag == PageDocument.StandardTypeTag) { PageDocument pageDoc = result.Document as PageDocument; return new SearchResultRow(pageDoc.PageInfo.FullName + Settings.PageExtension + "?" + queryStringKeywords, Page, FormattingPipeline.PrepareTitle(pageDoc.Title, false, FormattingContext.PageContent, pageDoc.PageInfo), result.Relevance.Value, GetExcerpt(pageDoc.PageInfo, result.Matches)); } else if(result.Document.TypeTag == MessageDocument.StandardTypeTag) { MessageDocument msgDoc = result.Document as MessageDocument; PageContent content = Content.GetPageContent(msgDoc.PageInfo, true); return new SearchResultRow(msgDoc.PageInfo.FullName + Settings.PageExtension + "?" + queryStringKeywords +"&Discuss=1#" + Tools.GetMessageIdForAnchor(msgDoc.DateTime), Message, FormattingPipeline.PrepareTitle(msgDoc.Title, false, FormattingContext.MessageBody, content.PageInfo) + " (" + FormattingPipeline.PrepareTitle(content.Title, false, FormattingContext.MessageBody, content.PageInfo) + ")", result.Relevance.Value, GetExcerpt(msgDoc.PageInfo, msgDoc.MessageID, result.Matches)); } else if(result.Document.TypeTag == FileDocument.StandardTypeTag) { FileDocument fileDoc = result.Document as FileDocument; return new SearchResultRow("GetFile.aspx?File=" + Tools.UrlEncode(fileDoc.Name.Substring(fileDoc.Provider.Length + 1)) + "&Provider=" + Tools.UrlEncode(fileDoc.Provider), File, fileDoc.Title, result.Relevance.Value, ""); } else if(result.Document.TypeTag == PageAttachmentDocument.StandardTypeTag) { PageAttachmentDocument attnDoc = result.Document as PageAttachmentDocument; PageContent content = Content.GetPageContent(attnDoc.Page, false); return new SearchResultRow(attnDoc.Page.FullName + Settings.PageExtension, Attachment, attnDoc.Title + " (" + FormattingPipeline.PrepareTitle(content.Title, false, FormattingContext.PageContent, content.PageInfo) + ")", result.Relevance.Value, ""); } else throw new NotSupportedException(); }
/// <summary> /// Performs a search in the index. /// </summary> /// <param name="query">The search query.</param> /// <param name="documentTypeTags">The document type tags to include in the search.</param> /// <param name="filterDocumentType"><c>true</c> to apply the filter on the document type.</param> /// <param name="options">The search options.</param> /// <param name="fetcher">An object that is able to fetch words.</param> /// <returns>The results.</returns> /// <exception cref="ArgumentNullException">If <paramref name="query"/> or <paramref name="fetcher"/> are <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="query"/> is empty.</exception> /// <exception cref="ArgumentNullException">If <paramref name="filterDocumentType"/> is <c>true</c> and <paramref name="documentTypeTags"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="filterDocumentType"/> is <c>true</c> and <paramref name="documentTypeTags"/> is empty.</exception> public static SearchResultCollection SearchInternal(string query, string[] documentTypeTags, bool filterDocumentType, SearchOptions options, IWordFetcher fetcher) { if(query == null) throw new ArgumentNullException("query"); if(query.Length == 0) throw new ArgumentException("Query cannot be empty", "query"); if(filterDocumentType && documentTypeTags == null) throw new ArgumentNullException("documentTypeTags"); if(filterDocumentType && documentTypeTags.Length == 0) throw new ArgumentException("documentTypeTags cannot be empty", "documentTypeTags"); if(fetcher == null) throw new ArgumentNullException("fetcher"); SearchResultCollection results = new SearchResultCollection(); query = query.ToLowerInvariant(); string[] queryWords = query.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); float totalRelevance = 0; Word word = null; foreach(string q in queryWords) { if(fetcher.TryGetWord(q, out word)) { foreach(IDocument doc in word.Occurrences.Keys) { // Skip documents with excluded tags if(filterDocumentType && !IsDocumentTypeTagIncluded(doc.TypeTag, documentTypeTags)) continue; foreach(BasicWordInfo info in word.Occurrences[doc]) { // If a search result is already present, add a new match to it, // otherwise create a new search result object WordInfo mi = new WordInfo(q, info.FirstCharIndex, info.WordIndex, info.Location); SearchResult res = results.GetSearchResult(doc); if(res == null) { res = new SearchResult(doc); res.Relevance.SetValue(info.Location.RelativeRelevance); res.Matches.Add(mi); results.Add(res); } else { // Avoid adding duplicate matches (happens when query contains the same word multiple times) if(!res.Matches.ContainsOccurrence(mi.Text, mi.FirstCharIndex)) { res.Matches.Add(mi); } res.Relevance.SetValue(res.Relevance.Value + info.Location.RelativeRelevance); } totalRelevance += info.Location.RelativeRelevance; } } } } if(options == SearchOptions.AllWords) { totalRelevance -= PurgeResultsForAllWords(results, queryWords); } else if(options == SearchOptions.ExactPhrase) { totalRelevance -= PurgeResultsForExactPhrase(results, queryWords); } else if(options == SearchOptions.AtLeastOneWord) { // Nothing to do } else throw new InvalidOperationException("Unsupported SearchOptions"); // Finalize relevance values for(int i = 0; i < results.Count; i++) { results[i].Relevance.Finalize(totalRelevance); } return results; }