Ejemplo n.º 1
0
        private IEnumerable <Document> GetRelatedAnnotations(RawSearchResultSet rawSearchResults, ICrmEntityQuery query)
        {
            Query textQuery;
            var   noteQuery   = new BooleanQuery();
            var   queryParser = new QueryParser(Index.Version, Index.ContentFieldName, Index.GetQuerySpecificAnalyzer(query.MultiLanguageEnabled, query.ContextLanguage));

            try
            {
                textQuery = queryParser.Parse(string.Format("+({0}) filename:({0}) notetext:({0}) _logicalname:annotation~0.9^0.3", query.QueryTerm));
            }
            catch (ParseException)
            {
                textQuery = queryParser.Parse(QueryParser.Escape(string.Format("+({0}) filename:({0}) notetext:({0}) _logicalname:annotation~0.9^0.3", query.QueryTerm)));
            }

            noteQuery.Add(textQuery, Occur.MUST);
            noteQuery.Add(new TermQuery(new Term("_logicalname", "annotation")), Occur.MUST);
            foreach (var scoreDoc in rawSearchResults.Results)
            {
                var resultField = _searcher.Doc(scoreDoc.Doc).GetField("_logicalname");
                if (resultField != null && resultField.StringValue == "knowledgearticle")
                {
                    var primaryKey = _searcher.Doc(scoreDoc.Doc).GetField("_primarykey");
                    noteQuery.Add(new TermQuery(new Term("annotation_knowledgearticleid", primaryKey.StringValue)), Occur.SHOULD);
                }
            }

            var rawNoteResults = GetRawSearchResults(noteQuery, 30, 0);

            return(rawNoteResults.Results.Select(rawNoteResult => _searcher.Doc(rawNoteResult.Doc)).ToList());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Override to return facets and sorting options.
        /// </summary>
        /// <param name="results">Search results to display to user.</param>
        /// <param name="approximateTotalHits">Estimate of the number of results.</param>
        /// <param name="pageNumber">The page number.</param>
        /// <param name="pageSize">The Page size.</param>
        /// <param name="rawSearchResultSet">The raw search result set, which contains the raw results and other search related info.</param>
        /// <returns>The result page to return to the user.</returns>
        protected override ICrmEntitySearchResultPage GenerateResultPage(ICollection <ICrmEntitySearchResult> results, int approximateTotalHits, int pageNumber, int pageSize, RawSearchResultSet rawSearchResultSet)
        {
            var resultOffset = (pageNumber - 1) * pageSize;

            var pageResults = results.Skip(resultOffset).Take(pageSize).ToList();

            return(new CrmEntitySearchResultPage(pageResults, approximateTotalHits, pageNumber, pageSize, rawSearchResultSet.FacetViews, rawSearchResultSet.SortingOptions));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Get the processed search results provided by the query available to the searching user.
        /// </summary>
        /// <param name="query">Search query.</param>
        /// <param name="searchLimit">Number of results to obtain from the underlying search library.</param>
        /// <param name="initialOffset">Number of already processed results to skip.</param>
        /// <param name="resultLimit">Number of results to return in the result page.</param>
        /// <param name="resultFactory">Factory to generate the ICrmEntitySearchResults</param>
        /// <param name="pageNumber">Page number</param>
        /// <param name="pageSize">Page size</param>
        /// <param name="results">Processed results so far.</param>
        /// <returns></returns>
        protected ICrmEntitySearchResultPage GetUserSearchResults(ICrmEntityQuery query, int searchLimit, int initialOffset, int resultLimit, ICrmEntitySearchResultFactory resultFactory, int pageNumber, int pageSize, ICollection <ICrmEntitySearchResult> results)
        {
            ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("(searchLimit={0},rawOffset={1},resultLimit={2})", searchLimit, initialOffset, resultLimit));
            RawSearchResultSet rawSearchResults = GetRawSearchResults(query, searchLimit, initialOffset);

            if (initialOffset >= rawSearchResults.TotalHits)
            {
                return(GenerateResultPage(results, rawSearchResults.TotalHits, pageNumber, pageSize, rawSearchResults));
            }

            var stopwatch = new Stopwatch();

            stopwatch.Start();
            var groupedNotes = new List <IGrouping <EntityReference, ICrmEntitySearchResult> >();
            var displayNotes = IsAnnotationSearchEnabled();

            if (displayNotes && !string.IsNullOrEmpty(query.QueryTerm))
            {
                var rawNotes = this.GetRelatedAnnotations(rawSearchResults, query);

                var notes =
                    rawNotes.Select(document => resultFactory.GetResult(document, 1, results.Count + 1)).ToList();

                //Grouping Notes by related Knowledge Articles
                groupedNotes =
                    notes.Where(note => note.EntityLogicalName == "annotation")
                    .GroupBy(note => note.Entity.GetAttributeValue <EntityReference>("objectid"))
                    .ToList();
            }

            var offsetForNextIteration = initialOffset;

            foreach (var scoreDoc in rawSearchResults.Results)
            {
                offsetForNextIteration++;

                var result = resultFactory.GetResult(_searcher.Doc(scoreDoc.Doc), scoreDoc.Score, results.Count + 1);

                // Not a valid user result, filter out
                if (result == null)
                {
                    continue;
                }

                if (result.EntityLogicalName == "knowledgearticle" && displayNotes)
                {
                    var relatedNotes = groupedNotes.Where(a => a.Key.Id == result.EntityID).SelectMany(i => i).Take(3).ToList();

                    if (relatedNotes.Any(note => note.Fragment == result.Fragment))
                    {
                        result.Fragment = GetKnowledgeArticleDescription(result);
                    }
                    result.Entity["relatedNotes"] = relatedNotes;
                }

                results.Add(result);

                if (results.Count >= resultLimit)
                {
                    stopwatch.Stop();

                    ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Gathered {0} results, done ({1}ms)", results.Count, stopwatch.ElapsedMilliseconds));

                    PortalFeatureTrace.TraceInstance.LogSearch(FeatureTraceCategory.Search, results.Count, stopwatch.ElapsedMilliseconds, string.Format("Gathered {0} results, done ({1}ms)", results.Count, stopwatch.ElapsedMilliseconds));

                    return(GenerateResultPage(results, rawSearchResults.TotalHits, pageNumber, pageSize, rawSearchResults));
                }
            }

            stopwatch.Stop();

            // We asked for more hits than we got back from Lucene, and we still didn't gather enough valid
            // results. That's all we're going to get, so the number of results we got is the number of hits.
            if (searchLimit >= rawSearchResults.TotalHits)
            {
                ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("All available results ({0}) gathered, done ({1}ms)", results.Count, stopwatch.ElapsedMilliseconds));

                PortalFeatureTrace.TraceInstance.LogSearch(FeatureTraceCategory.Search, results.Count, stopwatch.ElapsedMilliseconds, string.Format("All available results ({0}) gathered, done ({1}ms)", results.Count, stopwatch.ElapsedMilliseconds));

                return(GenerateResultPage(results, results.Count, pageNumber, pageSize, rawSearchResults));
            }

            ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("{0} results gathered so far ({1}ms)", results.Count, stopwatch.ElapsedMilliseconds));

            PortalFeatureTrace.TraceInstance.LogSearch(FeatureTraceCategory.Search, results.Count, stopwatch.ElapsedMilliseconds, string.Format("{0} results gathered so far ({1}ms)", results.Count, stopwatch.ElapsedMilliseconds));

            return(GetUserSearchResults(query, searchLimit * ExtendedSearchLimitMultiple, offsetForNextIteration, resultLimit, resultFactory, pageNumber, pageSize, results));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates a result page based off the processed search results.
        /// </summary>
        /// <param name="results">Search results to display to user.</param>
        /// <param name="approximateTotalHits">Estimate of the number of results.</param>
        /// <param name="pageNumber">The page number.</param>
        /// <param name="pageSize">The Page size.</param>
        /// <param name="rawSearchResultSet">The raw search result set, which contains the raw results and other search related info.</param>
        /// <returns>The result page to return to the user.</returns>
        protected virtual ICrmEntitySearchResultPage GenerateResultPage(ICollection <ICrmEntitySearchResult> results, int approximateTotalHits, int pageNumber, int pageSize, RawSearchResultSet rawSearchResultSet)
        {
            var resultOffset = (pageNumber - 1) * pageSize;

            var pageResults = results.Skip(resultOffset).Take(pageSize).ToList();

            return(new CrmEntitySearchResultPage(pageResults, approximateTotalHits, pageNumber, pageSize));
        }