public async Task GetDownloadDetails_Returns_Correct_Data()
        {
            var key = "*";

            var searchResult = new DocumentSearchResult <DownloadDetailsModel>(
                PopulateDownloadsData(),
                1,
                0,
                null,
                SearchContinuationToken.CreateTestToken("foo"));

            var clientMock = new Mock <IDownloadsIndexService>();

            var azureServiceMock = new Mock <IAzureService>();
            var searchTermFormattingServiceMock = new Mock <ISearchTermFormattingService>();

            azureServiceMock
            .Setup(m => m.SearchIndexAsync <DownloadDetailsModel>(clientMock.Object, key, It.IsAny <SearchParameters>()))
            .ReturnsAsync(searchResult);

            var mapper  = new AzureDownloadDataMapper();
            var service = new AzureDownloadsService(azureServiceMock.Object, mapper, clientMock.Object, searchTermFormattingServiceMock.Object);

            var result = (await service.GetDownloadDetails(key)).ToList();

            result.Count.Should().Be(6);
            result[0].Id.Should().Be("4");
            result[1].Id.Should().Be("8");
            result[2].Id.Should().Be("12");
            result[3].Id.Should().Be("2");
            result[4].Id.Should().Be("6");
            result[5].Id.Should().Be("10");
        }
예제 #2
0
        public void CanDeserializeTokenWithOnlyLink()
        {
            SearchContinuationToken token =
                JsonConvert.DeserializeObject <SearchContinuationToken>(TokenWithOnlyLinkJson);

            Assert.Equal(_tokenWithOnlyLink, token, _tokenComparer);
        }
        private bool ValidateAndTraceContinueSearch(
            SearchContinuationToken continuationToken,
            out string invocationId)
        {
            // Validate
            if (continuationToken == null)
            {
                throw new ArgumentNullException("continuationToken");
            }

            // Tracing
            bool shouldTrace = TracingAdapter.IsEnabled;

            invocationId = null;
            if (shouldTrace)
            {
                invocationId = TracingAdapter.NextInvocationId.ToString();
                Dictionary <string, object> tracingParameters = new Dictionary <string, object>();
                tracingParameters.Add("continuationToken", continuationToken);

                TracingAdapter.Enter(invocationId, this, "ContinueSearchAsync", tracingParameters);
            }

            return(shouldTrace);
        }
예제 #4
0
        public async Task GetLarsLearningDeliveries_Returns_Valid_Aims()
        {
            var learnAimRef      = "12345678";
            var azureLearningAim = new LearningAimModel
            {
                LearnAimRef = learnAimRef
            };
            var apiLearningAim = new Models.LearningAimModel
            {
                LearnAimRef = learnAimRef
            };

            var searchModel = new LearningAimsSearchModel
            {
                SearchTerm = learnAimRef
            };

            var searchResult = new DocumentSearchResult <LearningAimModel>(
                new List <SearchResult <LearningAimModel> >
            {
                new SearchResult <LearningAimModel>(azureLearningAim)
            },
                1,
                0,
                null,
                SearchContinuationToken.CreateTestToken("foo"));

            var mapperMock = new Mock <IMapper <LearningAimModel, Models.LearningAimModel> >();

            mapperMock.Setup(m => m.Map(azureLearningAim)).Returns(apiLearningAim);

            var indexServiceMock = new Mock <ILearningDeliveryIndexService>();

            var azureServiceMock = new Mock <IAzureService>();

            azureServiceMock
            .Setup(m => m.SearchIndexAsync <LearningAimModel>(indexServiceMock.Object, learnAimRef, It.IsAny <SearchParameters>()))
            .ReturnsAsync(searchResult);

            var queryServiceMock = new Mock <IODataQueryService>();
            var searchTermFormattingServiceMock = new Mock <ISearchTermFormattingService>();

            searchTermFormattingServiceMock
            .Setup(f => f.FormatSearchTerm(learnAimRef))
            .Returns(learnAimRef);

            var service = new AzureLearningAimsService(
                mapperMock.Object,
                indexServiceMock.Object,
                queryServiceMock.Object,
                azureServiceMock.Object,
                searchTermFormattingServiceMock.Object);

            var result = (await service.GetLarsLearningDeliveries(searchModel)).ToList();

            azureServiceMock.Verify(m => m.SearchIndexAsync <LearningAimModel>(indexServiceMock.Object, learnAimRef, It.IsAny <SearchParameters>()), Times.Once);

            result.Should().HaveCount(1);
            result.Single().Should().BeSameAs(apiLearningAim);
        }
        private Task <AzureOperationResponse <DocumentSearchResult <T> > > DoContinueSearchAsync <T>(
            SearchContinuationToken continuationToken,
            SearchRequestOptions searchRequestOptions,
            Dictionary <string, List <string> > customHeaders,
            CancellationToken cancellationToken,
            JsonSerializerSettings deserializerSettings)
        {
            // Validate
            if (Client.ApiVersion == null)
            {
                throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.ApiVersion");
            }

            Throw.IfArgumentNull(continuationToken, nameof(continuationToken));

            Guid?clientRequestId = searchRequestOptions?.ClientRequestId;

            // Tracing
            bool   shouldTrace  = ServiceClientTracing.IsEnabled;
            string invocationId = null;

            if (shouldTrace)
            {
                invocationId = ServiceClientTracing.NextInvocationId.ToString();
                var tracingParameters = new Dictionary <string, object>
                {
                    ["continuationToken"] = continuationToken,
                    ["clientRequestId"]   = clientRequestId,
                    ["cancellationToken"] = cancellationToken
                };

                ServiceClientTracing.Enter(invocationId, this, "ContinueSearch", tracingParameters);
            }

            bool useGet = continuationToken.NextPageParameters == null;

            if (useGet)
            {
                return(Client.DocumentsProxy.ContinueSearchGetWithHttpMessagesAsync <T>(
                           continuationToken.NextLink,
                           clientRequestId,
                           EnsureCustomHeaders(customHeaders),
                           shouldTrace,
                           invocationId,
                           cancellationToken,
                           responseDeserializerSettings: deserializerSettings));
            }
            else
            {
                return(Client.DocumentsProxy.ContinueSearchPostWithHttpMessagesAsync <T>(
                           continuationToken.NextLink,
                           continuationToken.NextPageParameters,
                           clientRequestId,
                           EnsureCustomHeaders(customHeaders),
                           shouldTrace,
                           invocationId,
                           cancellationToken,
                           responseDeserializerSettings: deserializerSettings));
            }
        }
예제 #6
0
        /// <summary>
        /// Get event list as per search and filter criteria.
        /// </summary>
        /// <param name="searchQuery">Query which the user had typed in Messaging Extension search field.</param>
        /// <param name="searchParameters">Search parameters for enhanced searching.</param>
        /// <returns>List of events.</returns>
        public async Task <IEnumerable <EventEntity> > GetEventsAsync(
            string searchQuery,
            SearchParameters searchParameters)
        {
            await this.EnsureInitializedAsync();

            var postSearchResult = await this.searchIndexClient.Documents.SearchAsync <EventEntity>(searchQuery, searchParameters);

            SearchContinuationToken continuationToken = null;
            var events = new List <EventEntity>();

            if (postSearchResult?.Results != null)
            {
                events.AddRange(postSearchResult.Results.Select(p => p.Document));
                continuationToken = postSearchResult.ContinuationToken;
            }

            while (continuationToken != null)
            {
                var searchResult = await this.searchIndexClient.Documents.ContinueSearchAsync <EventEntity>(continuationToken);

                if (searchResult?.Results != null)
                {
                    events.AddRange(searchResult.Results.Select(p => p.Document));
                    continuationToken = searchResult.ContinuationToken;
                }
            }

            return(events);
        }
 /// <summary>
 /// Retrieves the next page of search results from the Azure Search index.  (see
 /// <see href="https://msdn.microsoft.com/library/azure/dn798927.aspx"/> for more information)
 /// </summary>
 /// <param name='operations'>
 /// Reference to the Microsoft.Azure.Search.IDocumentOperations.
 /// </param>
 /// <param name="continuationToken">
 /// Encapsulates the state required to fetch the next page of search results from the index.
 /// </param>
 /// <returns>
 /// Response containing the documents matching the query.
 /// </returns>
 /// <remarks>
 /// The non-generic overloads of the ContinueSearch and ContinueSearchAsync methods make a best-effort attempt
 /// to map JSON types in the response payload to .NET types. See
 /// <see cref="IDocumentOperations.GetAsync(string, System.Collections.Generic.IEnumerable&lt;string&gt;, CancellationToken)"/>
 /// for more information.
 /// </remarks>
 public static DocumentSearchResponse ContinueSearch(
     this IDocumentOperations operations,
     SearchContinuationToken continuationToken)
 {
     return(Task.Factory.StartNew((object s) =>
     {
         return ((IDocumentOperations)s).ContinueSearchAsync(continuationToken);
     }
                                  , operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult());
 }
        public async Task <SearchResults <T> > Search(string searchText, SearchParameters searchParameters = null, bool allResults = false)
        {
            ISearchIndexClient client = await GetOrCreateIndex();

            try
            {
                searchText = ParseSearchText(searchText);

                DocumentSearchResult <T> azureSearchResult = await client.Documents.SearchAsync <T>(searchText, searchParameters ?? DefaultParameters);

                IEnumerable <SearchResult <T> > results = azureSearchResult.Results.Select(x => new SearchResult <T>
                {
                    HitHighLights = x.Highlights,
                    Result        = x.Document,
                    Score         = x.Score
                });

                SearchContinuationToken continuationToken = azureSearchResult.ContinuationToken;

                // only keep querying to return all items if we want all results to be returned
                while (allResults && continuationToken != null)
                {
                    DocumentSearchResult <T> continuationResult = await client.Documents.ContinueSearchAsync <T>(continuationToken);

                    results = results.Concat(continuationResult.Results.Select(x => new SearchResult <T>
                    {
                        HitHighLights = x.Highlights,
                        Result        = x.Document,
                        Score         = x.Score
                    }));
                    continuationToken = continuationResult.ContinuationToken;
                }

                var response = new SearchResults <T>
                {
                    SearchTerm = searchText,
                    TotalCount = azureSearchResult.Count,
                    Facets     = azureSearchResult.Facets?.Select(x => new Facet
                    {
                        Name        = x.Key,
                        FacetValues = x.Value.Where(f => !string.IsNullOrWhiteSpace(f.Value.ToString())).Select(m => new FacetValue
                        {
                            Name  = m.Value.ToString(),
                            Count = (int)(m.Count ?? 0)
                        })
                    }).ToList(),
                    Results = results.ToList()
                };
                return(response);
            }
            catch (Exception ex)
            {
                throw new FailedToQuerySearchException("Failed to query search", ex);
            }
        }
예제 #9
0
        public async Task <Result <T> > RunQuery <T>(string indexName,
                                                     SearchParameters searchParameters,
                                                     string key,
                                                     SearchContinuationToken continuationToken,
                                                     bool highScoring = false) where T : class
        {
            var results     = new List <T>();
            var queryResult = new Result <T>();

            try
            {
                var searchIndexClient = searchServiceClient.Indexes.GetClient(indexName);
                var headers           = new Dictionary <string, List <string> > {
                    { "x-ms-azs-return-searchid", new List <string> {
                          "true"
                      } }
                };

                AzureOperationResponse <DocumentSearchResult <T> > azureOperationsResponse;

                if (continuationToken != null)
                {
                    azureOperationsResponse = await searchIndexClient.Documents.ContinueSearchWithHttpMessagesAsync <T>(continuationToken).ConfigureAwait(false);
                }
                else
                {
                    azureOperationsResponse = await searchIndexClient.Documents.SearchWithHttpMessagesAsync <T>(key, searchParameters, customHeaders : headers).ConfigureAwait(false);
                }

                if (azureOperationsResponse.Response.IsSuccessStatusCode)
                {
                    var searchResults = azureOperationsResponse.Body.Results;
                    queryResult.Facet = azureOperationsResponse.Body.Facets;
                    if (highScoring && searchResults.Any(i => i.Score > 2))
                    {
                        results.AddRange(searchResults.Where(i => i.Score > 2).Select(i => i.Document));
                    }
                    else
                    {
                        results.AddRange(searchResults.Select(i => i.Document));
                    }

                    queryResult.ContinuationToken = azureOperationsResponse.Body.ContinuationToken;
                    queryResult.Collection        = results;
                }
            }
            catch (Exception ex)
            {
            }

            return(queryResult);
        }
예제 #10
0
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            SearchContinuationToken token = (SearchContinuationToken)value;

            var payload =
                new SearchContinuationTokenPayload()
            {
                NextLink           = token.NextLink,
                NextPageParameters = token.NextPageParameters
            };

            serializer.Serialize(writer, payload);
        }
        public Task <DocumentSearchResponse <T> > ContinueSearchAsync <T>(
            SearchContinuationToken continuationToken,
            CancellationToken cancellationToken) where T : class
        {
            string invocationId;
            bool   shouldTrace = ValidateAndTraceContinueSearch(continuationToken, out invocationId);

            return(DoContinueSearchAsync <DocumentSearchResponse <T>, SearchResult <T>, T>(
                       continuationToken.NextLink,
                       shouldTrace,
                       invocationId,
                       cancellationToken,
                       DeserializeForSearch <T>));
        }
        public Task <DocumentSearchResponse> ContinueSearchAsync(
            SearchContinuationToken continuationToken,
            CancellationToken cancellationToken)
        {
            string invocationId;
            bool   shouldTrace = ValidateAndTraceContinueSearch(continuationToken, out invocationId);

            return(DoContinueSearchAsync <DocumentSearchResponse, SearchResult, Document>(
                       continuationToken.NextLink,
                       shouldTrace,
                       invocationId,
                       cancellationToken,
                       DeserializeForSearch));
        }
        public Task <AzureOperationResponse <DocumentSearchResult <Document> > > ContinueSearchWithHttpMessagesAsync(
            SearchContinuationToken continuationToken,
            SearchRequestOptions searchRequestOptions         = default(SearchRequestOptions),
            Dictionary <string, List <string> > customHeaders = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var deserializerSettings = JsonUtility.CreateDocumentDeserializerSettings(Client.DeserializationSettings);

            return(DoContinueSearchAsync <Document>(
                       continuationToken,
                       searchRequestOptions,
                       customHeaders,
                       cancellationToken,
                       deserializerSettings));
        }
예제 #14
0
        /// <summary>
        /// Provide search result for table to be used by user's based on Azure Search service.
        /// </summary>
        /// <param name="searchScope">Scope of the search.</param>
        /// <param name="searchQuery">Query which the user had typed in Messaging Extension search field.</param>
        /// <param name="userObjectId">Azure Active Directory object id of user.</param>
        /// <param name="count">Number of search results to return.</param>
        /// <param name="skip">Number of search results to skip.</param>
        /// <param name="filterQuery">Filter bar based query.</param>
        /// <returns>List of search results.</returns>
        public async Task <IEnumerable <ProjectEntity> > GetProjectsAsync(
            ProjectSearchScope searchScope,
            string searchQuery,
            string userObjectId,
            int?count          = null,
            int?skip           = null,
            string filterQuery = null)
        {
            await this.EnsureInitializedAsync();

            IEnumerable <ProjectEntity> projects = new List <ProjectEntity>();
            var searchParameters = this.InitializeSearchParameters(searchScope, userObjectId, count, skip, filterQuery);

            SearchContinuationToken continuationToken = null;
            var projectsCollection = new List <ProjectEntity>();

            if (searchScope == ProjectSearchScope.SearchProjects && !string.IsNullOrWhiteSpace(searchQuery))
            {
                searchQuery = this.projectHelper.EscapeCharactersForSearchQuery(searchQuery);
            }

            var projectResult = await this.searchIndexClient.Documents.SearchAsync <ProjectEntity>(searchQuery, searchParameters);

            if (projectResult?.Results != null)
            {
                projectsCollection.AddRange(projectResult.Results.Select(p => p.Document));
                continuationToken = projectResult.ContinuationToken;
            }

            if (continuationToken == null)
            {
                return(projectsCollection);
            }

            do
            {
                var projectNextResult = await this.searchIndexClient.Documents.ContinueSearchAsync <ProjectEntity>(continuationToken);

                if (projectNextResult?.Results != null)
                {
                    projectsCollection.AddRange(projectNextResult.Results.Select(p => p.Document));
                    continuationToken = projectNextResult.ContinuationToken;
                }
            }while (continuationToken != null);

            return(projectsCollection);
        }
예제 #15
0
        /// <summary>
        /// Provides idea search results based on query details provided by the user.
        /// </summary>
        /// <param name="searchScope">Scope of the search.</param>
        /// <param name="searchQuery">Query which the user had typed in Messaging Extension search field.</param>
        /// <param name="userObjectId">Azure Active Directory object id of the user.</param>
        /// <param name="count">Number of search results to return.</param>
        /// <param name="skip">Number of search results to skip.</param>
        /// <param name="sortBy">Represents sorting type like: Popularity or Newest.</param>
        /// <param name="filterQuery">Filter bar based query.</param>
        /// <returns>List of search results.</returns>
        public async Task <IEnumerable <IdeaEntity> > GetTeamIdeasAsync(
            IdeaSearchScope searchScope,
            string searchQuery,
            string userObjectId,
            int?count          = null,
            int?skip           = null,
            string sortBy      = null,
            string filterQuery = null)
        {
            await this.EnsureInitializedAsync();

            var searchParameters = this.InitializeSearchParameters(searchScope, userObjectId, count, skip, sortBy, filterQuery);

            SearchContinuationToken continuationToken = null;
            var ideas = new List <IdeaEntity>();

            if (searchScope == IdeaSearchScope.SearchTeamPostsForTitleText && !string.IsNullOrWhiteSpace(searchQuery))
            {
                searchQuery = searchQuery.EscapeCharactersInQuery();
            }

            var ideaSearchResult = await this.searchIndexClient.Documents.SearchAsync <IdeaEntity>(searchQuery, searchParameters);

            if (ideaSearchResult?.Results != null)
            {
                ideas.AddRange(ideaSearchResult.Results.Select(p => p.Document));
                continuationToken = ideaSearchResult.ContinuationToken;
            }

            if (continuationToken == null)
            {
                return(ideas);
            }

            do
            {
                var searchResult = await this.searchIndexClient.Documents.ContinueSearchAsync <IdeaEntity>(continuationToken);

                if (searchResult?.Results != null)
                {
                    ideas.AddRange(searchResult.Results.Select(p => p.Document));
                    continuationToken = searchResult.ContinuationToken;
                }
            }while (continuationToken != null);

            return(ideas);
        }
        private static async Task <TResult> DoSearch <TResult>(ISearchIndexClient indexClient, string searchText, string[] facetFields,
                                                               SearchParameters searchParameters,
                                                               Func <SearchResults, TResult> searchResults,
                                                               Func <string, TResult> onFailure,
                                                               SearchContinuationToken continuationToken = default(SearchContinuationToken))
        {
            try
            {
                //searchParameters.
                var response = await indexClient.Documents.SearchAsync(searchText,
                                                                       searchParameters);

                var sR = new SearchResults();
                sR.Results = await GetAllResultsAsync(indexClient, response);

                if (facetFields.NullToEmpty().Any())
                {
                    sR.Facets = response.Facets.Select(facet =>
                    {
                        return(new KeyValuePair <string, Dictionary <string, long?> >(facet.Key, facet.Value.ToDictionary(item => item.Value.ToString(), item => item.Count)));
                    });
                }
                sR.Count = response.Count;
                return(searchResults(sR));
            } catch (Microsoft.Rest.Azure.CloudException clEx)
            {
                if (clEx.Response.StatusCode == HttpStatusCode.BadRequest &&
                    clEx.Body.Message.Contains("Only filterable fields can be used in filter expressions"))
                {
                    // This is a property that didn't get marked filterable.
                    // However, this is probably not something we should add to the TResult options
                }
                return(onFailure(clEx.Message));
            }

            //var continuationItems = new List<TResult>() as IEnumerable<TResult>;
            //if (null != response.ContinuationToken)
            //{
            //    continuationItems = await DoSearch(indexClient, response.ContinuationToken, facetFields, convertFunc, facetFunc, count.Invoke);
            //}
            //return items.Concat(continuationItems);
        }
예제 #17
0
        /// <summary>
        /// Provide search result for table to be used by user's based on Azure Search service.
        /// </summary>
        /// <param name="searchScope">Scope of the search.</param>
        /// <param name="searchQuery">Query which the user had typed in Messaging Extension search field.</param>
        /// <param name="userObjectId">Azure Active Directory object id of the user.</param>
        /// <param name="count">Number of search results to return.</param>
        /// <param name="skip">Number of search results to skip.</param>
        /// <param name="sortBy">Represents sorting type like: Popularity or Newest.</param>
        /// <param name="filterQuery">Filter bar based query.</param>
        /// <returns>List of search results.</returns>
        public async Task <IEnumerable <PostEntity> > GetPostsAsync(
            PostSearchScope searchScope,
            string searchQuery,
            string userObjectId,
            int?count          = null,
            int?skip           = null,
            int?sortBy         = null,
            string filterQuery = null)
        {
            await this.EnsureInitializedAsync();

            var searchParameters = this.InitializeSearchParameters(searchScope, userObjectId, count, skip, sortBy, filterQuery);

            SearchContinuationToken continuationToken = null;
            var posts            = new List <PostEntity>();
            var postSearchResult = await this.searchIndexClient.Documents.SearchAsync <PostEntity>(searchQuery, searchParameters);

            if (postSearchResult?.Results != null)
            {
                posts.AddRange(postSearchResult.Results.Select(p => p.Document));
                continuationToken = postSearchResult.ContinuationToken;
            }

            if (continuationToken == null)
            {
                return(posts);
            }

            do
            {
                var searchResult = await this.searchIndexClient.Documents.ContinueSearchAsync <PostEntity>(continuationToken);

                if (searchResult?.Results != null)
                {
                    posts.AddRange(searchResult.Results.Select(p => p.Document));
                    continuationToken = searchResult.ContinuationToken;
                }
            }while (continuationToken != null);

            return(posts);
        }
예제 #18
0
        public async Task <IEnumerable <TEntityType> > GetCompleteSet(string searchKey, string filter, string[] select = null, int takeCount = 1000)
        {
            var skippy = 0;

            SearchParameters parameters = new SearchParameters()
            {
                Filter = string.IsNullOrEmpty(filter) ? string.Empty : filter,
                Select = @select ?? new string[] { "*" },
                IncludeTotalResultCount = true,
                SearchMode = SearchMode.All,
                Skip       = skippy,
                Top        = takeCount
            };

            SearchContinuationToken continuationToken = null;
            var result      = new List <TEntityType>();
            var limitSearch =
                await IndexClient.Documents.SearchAsync <TEntityType>(
                    string.IsNullOrWhiteSpace(searchKey)? "*" : searchKey, parameters);

            var upperLimit = limitSearch.Count > 100000 ? 100000 : limitSearch.Count;

            parameters.IncludeTotalResultCount = false;
            while (skippy < upperLimit)
            {
                parameters.Skip = skippy;

                var thisResult = await IndexClient.Documents.SearchAsync <TEntityType>(string.IsNullOrEmpty(searchKey)? "*" : searchKey, parameters);

                result.AddRange(thisResult.Results.Select(x => x.Document));
                continuationToken = thisResult.ContinuationToken;

                skippy += thisResult.Results.Count;
            }

            return(result);
        }
 /// <summary>
 /// Retrieves the next page of search results from the Azure Search index.  (see
 /// <see href="https://msdn.microsoft.com/library/azure/dn798927.aspx"/> for more information)
 /// </summary>
 /// <param name='operations'>
 /// Reference to the Microsoft.Azure.Search.IDocumentOperations.
 /// </param>
 /// <param name="continuationToken">
 /// Encapsulates the state required to fetch the next page of search results from the index.
 /// </param>
 /// <returns>
 /// Response containing the documents matching the query.
 /// </returns>
 /// <remarks>
 /// The non-generic overloads of the ContinueSearch and ContinueSearchAsync methods make a best-effort attempt
 /// to map JSON types in the response payload to .NET types. See
 /// <see cref="IDocumentOperations.GetAsync(string, System.Collections.Generic.IEnumerable&lt;string&gt;, CancellationToken)"/>
 /// for more information.
 /// </remarks>
 public static Task <DocumentSearchResponse> ContinueSearchAsync(
     this IDocumentOperations operations,
     SearchContinuationToken continuationToken)
 {
     return(operations.ContinueSearchAsync(continuationToken, CancellationToken.None));
 }
 /// <summary>
 /// Retrieves the next page of search results from the Azure Search index.  (see
 /// <see href="https://msdn.microsoft.com/library/azure/dn798927.aspx"/> for more information)
 /// </summary>
 /// <typeparam name="T">
 /// The CLR type that maps to the index schema. Instances of this type can be retrieved as documents
 /// from the index.
 /// </typeparam>
 /// <param name='operations'>
 /// Reference to the Microsoft.Azure.Search.IDocumentOperations.
 /// </param>
 /// <param name="continuationToken">
 /// Encapsulates the state required to fetch the next page of search results from the index.
 /// </param>
 /// <returns>
 /// Response containing the documents matching the query.
 /// </returns>
 /// <remarks>
 /// The generic overloads of the ContinueSearch and ContinueSearchAsync methods support mapping of
 /// Azure Search field types to .NET types via the type parameter T. See
 /// <see cref="IDocumentOperations.GetAsync&lt;T&gt;(string, System.Collections.Generic.IEnumerable&lt;string&gt;, CancellationToken)"/>
 /// for more details on the type mapping.
 /// </remarks>
 public static Task <DocumentSearchResponse <T> > ContinueSearchAsync <T>(
     this IDocumentOperations operations,
     SearchContinuationToken continuationToken) where T : class
 {
     return(operations.ContinueSearchAsync <T>(continuationToken, CancellationToken.None));
 }
예제 #21
0
        /// <summary>
        /// Continues searching documents.
        /// </summary>
        /// <returns>The documents.</returns>
        /// <param name="searchContinuationToken">Continuation token.</param>
        /// <typeparam name="T">The type of object.</typeparam>
        public async Task <DocumentSearchResult <T> > ContinueSearchDocumentsAsync <T>(SearchContinuationToken searchContinuationToken) where T : class, new()
        {
            var originalSearchResult = await _searchClient.Documents.ContinueSearchAsync <ShushuIndex>(searchContinuationToken).ConfigureAwait(false);

            var newSearchResult = new List <SearchResult <T> >();

            if (originalSearchResult != null)
            {
                foreach (var result in originalSearchResult.Results)
                {
                    var newResult = new SearchResult <T>(result.Document.MapFromIndex <T>(), result.Score, result.Highlights);

                    newSearchResult.Add(newResult);
                }
            }

            return(new DocumentSearchResult <T>(newSearchResult,
                                                originalSearchResult.Count,
                                                originalSearchResult.Coverage,
                                                originalSearchResult.Facets,
                                                originalSearchResult.ContinuationToken
                                                ));
        }
        private async Task <IEnumerable <TResult> > DoSearch <TResult>(ISearchIndexClient indexClient, SearchContinuationToken continuationToken, string[] facetFields,
                                                                       Func <TResult, TResult> convertFunc, Action <string, Dictionary <string, long?> > facetFunc, Action <long?> count)
            where TResult : class, new()
        {
            var response = await indexClient.Documents.ContinueSearchAsync <TResult>(continuationToken);

            var items = response.Results.Select(item => convertFunc(item.Document));

            if (default(string[]) != facetFields)
            {
                foreach (var facet in response.Facets)
                {
                    var facetValues = facet.Value.ToDictionary(item => item.Value.ToString(), item => item.Count);
                    facetFunc.Invoke(facet.Key, facetValues);
                }
            }
            count.Invoke(response.Count);

            var continuationItems = new List <TResult>() as IEnumerable <TResult>;

            if (null != response.ContinuationToken)
            {
                continuationItems = await DoSearch(indexClient, response.ContinuationToken, facetFields, convertFunc, facetFunc, count.Invoke);
            }
            return(items.Concat(continuationItems));
        }