Ejemplo n.º 1
0
        public void Search( )
        {
            // Basic integration test: search algorithms are already extensively tested with InMemoryIndexBase

            MockRepository mocks = new MockRepository( );

            IIndexConnector conn    = mocks.StrictMock <IIndexConnector>( );
            IWordFetcher    fetcher = mocks.StrictMock <IWordFetcher>( );

            Word dummy;

            Expect.Call(fetcher.TryGetWord("test", out dummy)).Return(false);
            Expect.Call(fetcher.TryGetWord("query", out dummy)).Return(false);
            fetcher.Dispose( );
            LastCall.On(fetcher);

            Expect.Call(conn.GetWordFetcher( )).Return(fetcher);

            mocks.ReplayAll( );

            SqlIndex index = new SqlIndex(conn);

            Assert.AreEqual(0, index.Search(new SearchParameters("test query")).Count, "Wrong search result count");

            mocks.VerifyAll( );
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Performs a search in the index.
        /// </summary>
        /// <param name="parameters">The search parameters.</param>
        /// <returns>The results.</returns>
        public SearchResultCollection Search(SearchParameters parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            using (IWordFetcher fetcher = connector.GetWordFetcher())
            {
                if (parameters.DocumentTypeTags == null)
                {
                    return(ScrewTurn.Wiki.SearchEngine.Tools.SearchInternal(parameters.Query, null, false, parameters.Options, fetcher));
                }
                return(ScrewTurn.Wiki.SearchEngine.Tools.SearchInternal(parameters.Query, parameters.DocumentTypeTags, true, parameters.Options, fetcher));
            }
        }
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 4
0
        /// <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;
        }