Пример #1
0
        public virtual async Task <SearchResult> SearchAsync(string term,
                                                             int?filterByCategory         = null,
                                                             int languageId               = -1,
                                                             PostType?postType            = null,
                                                             SearchPlace searchPlace      = SearchPlace.Anywhere,
                                                             SearchResultSortType orderBy = SearchResultSortType.Score,
                                                             int maxResult    = 1000,
                                                             bool exactSearch = false)
        {
            var result = new SearchResult();

            term = term.Trim();

            //replace multiple spaces with a single space
            RegexOptions options = RegexOptions.None;
            Regex        regex   = new Regex("[ ]{2,}", options);

            term = regex.Replace(term, " ");

            if (string.IsNullOrWhiteSpace(term))
            {
                return(result);
            }

            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();
            try
            {
                await Task.Run(() =>
                {
                    using (var directory = FSDirectory.Open(new DirectoryInfo(_indexFilesPath)))
                    {
                        using (var searcher = new IndexSearcher(directory, readOnly: true))
                        {
                            var searchInFields = new List <string>();
                            if (searchPlace == SearchPlace.Anywhere)
                            {
                                searchInFields.AddRange(new string[] { "Title", "Description", "Keywords", "Tags" });
                            }
                            else
                            {
                                if (searchPlace.HasFlagFast(SearchPlace.Title))
                                {
                                    searchInFields.Add("Title");
                                }

                                if (searchPlace.HasFlagFast(SearchPlace.Description))
                                {
                                    searchInFields.Add("Description");
                                }

                                if (searchPlace.HasFlagFast(SearchPlace.Keywords))
                                {
                                    searchInFields.Add("Keywords");
                                }

                                if (searchPlace.HasFlagFast(SearchPlace.Tags))
                                {
                                    searchInFields.Add("Tags");
                                }
                            }

                            BooleanFilter filter = null;
                            if (languageId > -1 || filterByCategory != null || postType != null)
                            {
                                filter = new BooleanFilter();
                                if (languageId > -1)
                                {
                                    filter.Add(new FilterClause(
                                                   new QueryWrapperFilter(new TermQuery(new Term("LanguageId", languageId.ToString()))),
                                                   Occur.MUST));
                                }
                                if (filterByCategory != null)
                                {
                                    filter.Add(new FilterClause(
                                                   new QueryWrapperFilter(new TermQuery(new Term("Categories",
                                                                                                 filterByCategory.Value.ToString()))), Occur.MUST));
                                }
                                if (postType != null)
                                {
                                    filter.Add(new FilterClause(
                                                   new QueryWrapperFilter(new TermQuery(new Term("PostType",
                                                                                                 postType.Value.ToString()))), Occur.MUST));
                                }
                            }

                            var currentSettings = _settingService.LoadSetting <SiteSettings>();
                            if (!currentSettings.EnableBlog)
                            {
                                //Filter Blog Posts if Blog is disabled
                                if (filter == null)
                                {
                                    filter = new BooleanFilter();
                                }
                                filter.Add(new FilterClause(
                                               new QueryWrapperFilter(new TermQuery(new Term("PostType",
                                                                                             PostType.BlogPost.ToString()))), Occur.MUST_NOT));
                            }

                            Sort sort = new Sort(SortField.FIELD_SCORE);

                            switch (orderBy)
                            {
                            case SearchResultSortType.NumberOfVisits:
                                sort = new Sort(new SortField("NumberOfVisit", SortField.INT, true));
                                break;

                            case SearchResultSortType.PublishDate:
                                sort = new Sort(new SortField("PublishDate", SortField.LONG, true));
                                break;

                            case SearchResultSortType.LastUpDate:
                                sort = new Sort(new SortField("LastUpDate", SortField.LONG, true));
                                break;
                            }

                            var analyzer       = new StandardAnalyzer(Version);
                            var parser         = new MultiFieldQueryParser(Version, searchInFields.ToArray(), analyzer);
                            QueryScorer scorer = null;
                            var hits           = new List <ScoreDoc>();
                            Query query        = null;
                            if (exactSearch)
                            {
                                query = ParseQuery(term, parser);
                                hits.AddRange(searcher.Search(query, filter, maxResult, sort).ScoreDocs);
                            }
                            else
                            {
                                query = ParseQuery($"(\"{term}\")", parser);
                                hits.AddRange(searcher.Search(query, filter, maxResult, sort).ScoreDocs);
                                query = ParseQuery($"({term.Replace(" ", "*")})", parser);
                                hits.AddRange(searcher.Search(query, filter, maxResult, sort).ScoreDocs);
                                query = ParseQuery($"(+{term.Trim().Replace(" ", " +")})", parser);
                                hits.AddRange(searcher.Search(query, filter, maxResult, sort).ScoreDocs);
                                query = ParseQuery(term, parser);
                                hits.AddRange(searcher.Search(query, filter, maxResult, sort).ScoreDocs);
                            }

                            scorer = new QueryScorer(query);

                            if (hits.Count == 0)
                            {
                                term   = SearchByPartialWords(term);
                                query  = ParseQuery(term, parser);
                                scorer = new QueryScorer(query);
                                hits.AddRange(searcher.Search(query, filter, maxResult, sort).ScoreDocs);
                            }

                            var formatter = new SimpleHTMLFormatter(
                                "<span class='badge badge-warning'>",
                                "</span>");
                            var fragmenter  = new SimpleFragmenter(300);
                            var highlighter = new Highlighter(formatter, scorer)
                            {
                                TextFragmenter = fragmenter
                            };

                            foreach (var scoreDoc in hits)
                            {
                                var doc = searcher.Doc(scoreDoc.Doc);
                                result.Documents.Add(new SearchResultDocument()
                                {
                                    DocumentId       = int.Parse(doc.Get("ID")),
                                    LanguageId       = int.Parse(doc.Get("LanguageId")),
                                    LanguageIsoCode  = doc.Get("LanguageCode"),
                                    Score            = scoreDoc.Score,
                                    DocumentTitle    = GetHighlight("Title", highlighter, analyzer, doc.Get("Title"), false),
                                    DocumentBody     = GetHighlight("Description", highlighter, analyzer, doc.Get("Description"), true),
                                    DocumentKeywords = doc.Get("Keywords"),
                                    DocumentTags     = doc.Get("Tags"),
                                });
                            }

                            result.Documents = result.Documents.DistinctBy(p => new { p.DocumentId })
                                               .ToList();

                            analyzer.Close();

                            //SuggestSimilar
                            using (var spellDirectory = FSDirectory.Open(new DirectoryInfo(_spellFilesPath)))
                            {
                                using (var spellChecker = new SpellChecker.Net.Search.Spell.SpellChecker(spellDirectory))
                                {
                                    result.SuggestSimilar.AddRange(spellChecker.SuggestSimilar(term, 10, null, null, true));
                                }
                            }
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                result.Error    = ex;
                result.HasError = true;
            }

            watch.Stop();
            result.ElapsedMilliseconds = watch.ElapsedMilliseconds;

            _eventPublisher.Publish(new SearchEvent(term, filterByCategory, languageId, postType, searchPlace, maxResult, result));

            return(result);
        }
Пример #2
0
        public virtual SearchResult MoreLikeThis(int postId, int?filterByCategory = null, int languageId = -1, PostType?postType = null, SearchPlace searchPlace = SearchPlace.Title | SearchPlace.Description,
                                                 int maxResult = 5, SearchResultSortType orderBy         = SearchResultSortType.Score)
        {
            var result = new SearchResult();

            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();
            try
            {
                using (var directory = FSDirectory.Open(new DirectoryInfo(_indexFilesPath)))
                {
                    using (var searcher = new IndexSearcher(directory, readOnly: true))
                    {
                        var docNumber = GetLuceneDocNumber(postId, searcher);

                        if (docNumber == -1)
                        {
                            return(result);
                        }

                        var searchInFields = new List <string>();
                        if (searchPlace == SearchPlace.Anywhere)
                        {
                            searchInFields.AddRange(new string[] { "Title", "Description", "Keywords", "Tags" });
                        }
                        else
                        {
                            if (searchPlace.HasFlagFast(SearchPlace.Title))
                            {
                                searchInFields.Add("Title");
                            }

                            if (searchPlace.HasFlagFast(SearchPlace.Description))
                            {
                                searchInFields.Add("Description");
                            }

                            if (searchPlace.HasFlagFast(SearchPlace.Keywords))
                            {
                                searchInFields.Add("Keywords");
                            }

                            if (searchPlace.HasFlagFast(SearchPlace.Tags))
                            {
                                searchInFields.Add("Tags");
                            }
                        }

                        var analyzer     = new StandardAnalyzer(Version);
                        var moreLikeThis = new MoreLikeThis(searcher.IndexReader)
                        {
                            Analyzer = analyzer
                        };
                        moreLikeThis.SetFieldNames(searchInFields.ToArray());
                        moreLikeThis.MinDocFreq  = 1;
                        moreLikeThis.MinTermFreq = 1;
                        moreLikeThis.Boost       = true;

                        var query = moreLikeThis.Like(docNumber);

                        var filter = new BooleanFilter();

                        filter.Add(new FilterClause(
                                       new QueryWrapperFilter(new TermQuery(new Term("ID",
                                                                                     postId.ToString()))),
                                       Occur.MUST_NOT));

                        if (languageId > -1)
                        {
                            filter.Add(new FilterClause(
                                           new QueryWrapperFilter(new TermQuery(new Term("LanguageId",
                                                                                         languageId.ToString()))),
                                           Occur.MUST));
                        }
                        if (filterByCategory != null)
                        {
                            filter.Add(new FilterClause(
                                           new QueryWrapperFilter(new TermQuery(new Term("Categories",
                                                                                         filterByCategory.Value.ToString()))), Occur.MUST));
                        }
                        if (postType != null)
                        {
                            filter.Add(new FilterClause(
                                           new QueryWrapperFilter(new TermQuery(new Term("PostType",
                                                                                         postType.Value.ToString()))), Occur.MUST));
                        }

                        Sort sort = new Sort(SortField.FIELD_SCORE);

                        switch (orderBy)
                        {
                        case SearchResultSortType.NumberOfVisits:
                            sort = new Sort(new SortField("NumberOfVisit", SortField.INT, true));
                            break;

                        case SearchResultSortType.PublishDate:
                            sort = new Sort(new SortField("PublishDate", SortField.LONG, true));
                            break;

                        case SearchResultSortType.LastUpDate:
                            sort = new Sort(new SortField("LastUpDate", SortField.LONG, true));
                            break;
                        }

                        var hits = searcher.Search(query, filter, maxResult, sort).ScoreDocs;

                        foreach (var scoreDoc in hits)
                        {
                            var doc = searcher.Doc(scoreDoc.Doc);
                            result.Documents.Add(new SearchResultDocument()
                            {
                                DocumentId       = int.Parse(doc.Get("ID")),
                                LanguageId       = int.Parse(doc.Get("LanguageId")),
                                LanguageIsoCode  = doc.Get("LanguageCode"),
                                Score            = scoreDoc.Score,
                                DocumentTitle    = doc.Get("Title"),
                                DocumentBody     = doc.Get("Description"),
                                DocumentKeywords = doc.Get("Keywords"),
                                DocumentTags     = doc.Get("Tags"),
                            });
                        }

                        result.Documents = result.Documents.DistinctBy(p => new { p.DocumentId })
                                           .ToList();

                        analyzer.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                result.Error    = ex;
                result.HasError = true;
            }

            watch.Stop();
            result.ElapsedMilliseconds = watch.ElapsedMilliseconds;

            return(result);
        }