Example #1
0
        // Merge facets across multiple search services
        static void MergeFacets(IDictionary <string, IList <FacetResult> > singleServiceFacets, MultiSearchFacets mergedFacets)
        {
            foreach (KeyValuePair <string, IList <FacetResult> > resultFacets in singleServiceFacets)
            {
                string fieldName = resultFacets.Key;
                IList <FacetResult> serviceFacets = resultFacets.Value;
                if (mergedFacets.Facets.TryGetValue(fieldName, out List <MultiSearchFacet> multiServiceFacets))
                {
                    // If a facet can be merged into an existing multi-service facet, combine the counts
                    // Otherwise, add a new multi-service facet matching the existing facet
                    foreach (FacetResult facet in serviceFacets)
                    {
                        bool foundFacet = false;
                        foreach (MultiSearchFacet multiServiceFacet in multiServiceFacets)
                        {
                            if (multiServiceFacet.CanMergeFacet(facet))
                            {
                                foundFacet = true;
                                multiServiceFacet.Count += facet.Count.Value;
                                break;
                            }
                        }

                        if (!foundFacet)
                        {
                            multiServiceFacets.Add(new MultiSearchFacet(facet));
                        }
                    }
                }
                else
                {
                    // Initialize the multi-service facet list with the facets from this service for this field
                    mergedFacets.Facets.Add(fieldName, serviceFacets.Select(f => new MultiSearchFacet(f)).ToList());
                }
            }
        }
Example #2
0
        // Run the query and combine results across multiple services
        static async Task <(int, List <MultiSearchResult>, MultiSearchFacets)> RunQueryAsync(string query, int pageNumber, int pageSize, string searchFields, string facets, List <Service> services)
        {
            // Page results from all services
            var searchResults = new List <IAsyncEnumerator <MultiSearchResultsPage> >();

            foreach (Service service in services)
            {
                IAsyncEnumerable <MultiSearchResultsPage> response = SearchAsync(service, query, pageSize, searchFields, facets);
                searchResults.Add(response.GetAsyncEnumerator());
            }

            // Merge each individual page from every service
            // Sort the combined page by result score
            int currentPageNumber = 0;
            var currentPage       = new List <MultiSearchResult>();
            var mergedFacets      = new MultiSearchFacets();

            do
            {
                // Combine the current page of results from each service
                // If the service has no more results, it is discarded
                var resultPages       = new List <MultiSearchResultsPage>();
                var nextSearchResults = new List <IAsyncEnumerator <MultiSearchResultsPage> >();
                foreach (IAsyncEnumerator <MultiSearchResultsPage> pageEnumerator in searchResults)
                {
                    if (await pageEnumerator.MoveNextAsync())
                    {
                        resultPages.Add(pageEnumerator.Current);
                        nextSearchResults.Add(pageEnumerator);
                    }
                }

                searchResults = nextSearchResults;
                var mergedSearchResults = new List <MultiSearchResult>();
                foreach (MultiSearchResultsPage resultPage in resultPages)
                {
                    foreach (SearchResult <BookModel> result in resultPage.Page)
                    {
                        mergedSearchResults.Add(new MultiSearchResult {
                            Service = resultPage.Service, Result = result
                        });
                    }

                    if (resultPage.Facets != null)
                    {
                        MergeFacets(resultPage.Facets, mergedFacets);
                    }
                }

                // Sort the combined pages by score descending
                mergedSearchResults.Sort((a, b) =>
                {
                    MultiSearchResult resultA = a;
                    MultiSearchResult resultB = b;
                    if (resultA.Result.Score.HasValue && resultB.Result.Score.HasValue)
                    {
                        return(resultB.Result.Score.Value.CompareTo(resultA.Result.Score.Value));
                    }

                    if (resultA.Result.Score.HasValue && !resultB.Result.Score.HasValue)
                    {
                        return(-1);
                    }

                    if (!resultA.Result.Score.HasValue && resultB.Result.Score.HasValue)
                    {
                        return(1);
                    }

                    return(0);
                });

                // Return sub-pages of results from the combined page
                foreach (MultiSearchResult mergedSearchResult in mergedSearchResults)
                {
                    currentPage.Add(mergedSearchResult);
                    if (currentPage.Count == pageSize)
                    {
                        if (currentPageNumber == pageNumber)
                        {
                            return(currentPageNumber, currentPage, mergedFacets);
                        }

                        currentPage.Clear();
                        currentPageNumber++;
                    }
                }
            }while (searchResults.Any());

            // Return any leftover results as the last page
            return(currentPageNumber, currentPage, mergedFacets);
        }