public virtual CategorySearchResult SearchCategories(string scope, ISearchCriteria criteria, CategoryResponseGroup responseGroup) { var items = new List <Category>(); var itemsOrderedList = new List <string>(); var foundItemCount = 0; var dbItemCount = 0; var searchRetry = 0; //var myCriteria = criteria.Clone(); var myCriteria = criteria; ISearchResults <DocumentDictionary> searchResults = null; do { // Search using criteria, it will only return IDs of the items searchResults = _searchProvider.Search <DocumentDictionary>(scope, criteria); searchRetry++; if (searchResults == null || searchResults.Documents == null) { continue; } //Get only new found itemIds var uniqueKeys = searchResults.Documents.Select(x => x.Id.ToString()).Except(itemsOrderedList).ToArray(); foundItemCount = uniqueKeys.Length; if (!searchResults.Documents.Any()) { continue; } itemsOrderedList.AddRange(uniqueKeys); // if we can determine catalog, pass it to the service string catalog = null; if (criteria is CatalogItemSearchCriteria) { catalog = (criteria as CatalogItemSearchCriteria).Catalog; } // Now load items from repository var currentItems = _categoryService.GetByIds(uniqueKeys.ToArray(), responseGroup, catalog); var orderedList = currentItems.OrderBy(i => itemsOrderedList.IndexOf(i.Id)); items.AddRange(orderedList); dbItemCount = currentItems.Length; //If some items where removed and search is out of sync try getting extra items if (foundItemCount > dbItemCount) { //Retrieve more items to fill missing gap myCriteria.RecordsToRetrieve += (foundItemCount - dbItemCount); } }while (foundItemCount > dbItemCount && searchResults != null && searchResults.Documents.Any() && searchRetry <= 3 && (myCriteria.RecordsToRetrieve + myCriteria.StartingRecord) < searchResults.TotalCount); var response = new CategorySearchResult(); if (items != null) { var categoryDtos = new ConcurrentBag <CatalogModule.Web.Model.Category>(); Parallel.ForEach(items, (x) => { categoryDtos.Add(x.ToWebModel(_blobUrlResolver)); }); response.Categories = categoryDtos.OrderBy(i => itemsOrderedList.IndexOf(i.Id)).ToArray(); } if (searchResults != null) { response.TotalCount = searchResults.TotalCount; } return(response); }
public virtual CategorySearchResult SearchCategories(string scope, ISearchCriteria criteria, CategoryResponseGroup responseGroup) { var response = new CategorySearchResult(); var searchResults = _searchProvider.Search <DocumentDictionary>(scope, criteria); if (searchResults?.Documents != null) { var categoryDtos = new ConcurrentBag <CatalogModule.Web.Model.Category>(); var taskList = new List <Task>(); var documents = searchResults.Documents; if (_settingsManager.GetValue("VirtoCommerce.SearchApi.UseFullObjectIndexStoring", true)) { var fullIndexedDocuments = documents.Where(doc => doc.ContainsKey(IndexHelper.ObjectFieldName) && !string.IsNullOrEmpty(doc[IndexHelper.ObjectFieldName].ToString())).ToList(); documents = documents.Except(fullIndexedDocuments).ToList(); var deserializeProductsTask = Task.Factory.StartNew(() => { Parallel.ForEach(fullIndexedDocuments, new ParallelOptions { MaxDegreeOfParallelism = 5 }, doc => { var category = doc.GetObjectFieldValue <CatalogModule.Web.Model.Category>(); categoryDtos.Add(category); }); }); taskList.Add(deserializeProductsTask); } if (documents.Any()) { var loadProductsTask = Task.Factory.StartNew(() => { string catalog = null; var catalogItemSearchCriteria = criteria as CatalogItemSearchCriteria; if (catalogItemSearchCriteria != null) { catalog = catalogItemSearchCriteria.Catalog; } var categoryIds = documents.Select(x => x.Id.ToString()).Distinct().ToArray(); if (categoryIds.Any()) { // Now load items from repository var categories = _categoryService.GetByIds(categoryIds, responseGroup, catalog); Parallel.ForEach(categories, x => { categoryDtos.Add(x.ToWebModel(_blobUrlResolver)); }); } } ); taskList.Add(loadProductsTask); } Task.WaitAll(taskList.ToArray()); //Preserver original sorting order var orderedIds = searchResults.Documents.Select(x => x.Id.ToString()).ToList(); response.Categories = categoryDtos.OrderBy(i => orderedIds.IndexOf(i.Id)).ToArray(); } if (searchResults != null) { response.TotalCount = searchResults.TotalCount; } return(response); }