public static Models.Search.SearchResults SearchProducts(AccountManagementService.Account account, string text, string filter = null, string orderBy = "relevance", int skip = 0, int top = 120, bool locationSort = false, string locationSortString = null, bool includeHidden = false) { if (top > 120) { //We do not ever allow more than 120 results per page in search top = 120; } //ProductResults productResults = null; //List<ProductDocumentModel> products = null; //dynamic products = null; DocumentSearchResult azuresearchresult = null; //Get from cache first var accountSearchIndex = Common.SearchIndexCache[account.ProductSearchIndex] as ISearchIndexClient; if (accountSearchIndex == null) { //Not in cache, create: ---------------------------- //Get client for this accounts search index (Moved to partitioning) //var accountSearchIndex = CoreServices.SearchServiceQueryClient.Indexes.GetClient(account.ProductSearchIndex); //Get search partition for this account, create client and connect to index: ======================================================= if (CoreServices.PlatformSettings.SearchParitions == null || CoreServices.PlatformSettings.SearchParitions.ToList().Count == 0) { //No Search Partitions Available in Static List, refresh list from Core Services Common.RefreshPlatformSettings(); } var searchPartition = CoreServices.PlatformSettings.SearchParitions.FirstOrDefault(partition => partition.Name == account.SearchPartition); if (searchPartition == null) { //May be a new partition, refresh platform setting and try again Common.RefreshPlatformSettings(); searchPartition = CoreServices.PlatformSettings.SearchParitions.FirstOrDefault(partition => partition.Name == account.SearchPartition); } var searchServiceClient = new SearchServiceClient(searchPartition.Name, new SearchCredentials(searchPartition.Key)); accountSearchIndex = searchServiceClient.Indexes.GetClient(account.ProductSearchIndex); //Store in cache: --------------------- Common.SearchIndexCache.Set(account.ProductSearchIndex, accountSearchIndex, new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(Common.SearchIndexClientCacheTimeInMinutes) }); } //Prepare the query var searchParameters = new SearchParameters(); if (includeHidden == false) { if (String.IsNullOrEmpty(filter)) { filter = "(visible eq true)"; } else { filter += " and (visible eq true)"; } } //Assign filters searchParameters.Filter = filter; //Add location sorting first (always supercedes others) if applicable if (locationSort) { //include location sorting //if (locationSortType == "point") //{ searchParameters.OrderBy.Add(locationSortString); //} //else if (locationSortType == "bounds") //{ //} } searchParameters.Skip = skip; searchParameters.Top = top; //We only add ordering and result count if we ask for MORE than 1 item back searchParameters.OrderBy = new List <string>(); if (top > 1) { if (orderBy.ToLower() != "relevance") { var orderByArray = orderBy.Split(','); searchParameters.OrderBy.Add(orderBy); } searchParameters.IncludeTotalResultCount = true; } //build strings to search against: //TO DO: // bool listingImagesOnly = true; //bool includesLocationData = false; //<--If true we will need to merge location Metadata and remove Metadata field if (top == 1) { //This uses the Details Property Fields: //$select=categoryNameKey,categoryName,orderId,subcategoryName listingImagesOnly = false; //<--Get all images for details searchParameters.Select = GetSearchFields(account.AccountNameKey, PropertyListType.Details); //<-- InOrder??? } else { //This uses the Listings Property Fields: //$select=categoryNameKey,categoryName,orderId,subcategoryName searchParameters.Select = GetSearchFields(account.AccountNameKey, PropertyListType.Listings); //<-- InOrder??? } //If the query contains dashes and no spaces, wrap it in quotes in order to get GUIDS and SKUS (The indexer replaces "-" with " " when storing into search) try { if (text.Contains("-")) { if (!text.Contains(" ")) { text = "\"" + text + "\""; } } } catch { } //Perform the search //NOTE: We add a wildcard at the end to get better results from text searches azuresearchresult = accountSearchIndex.Documents.Search(text + "*", searchParameters); #region Loop through each search result, transform into SearchResult object and append associated 'Listing' type ImageRecords to each results var searchresults = new Models.Search.SearchResults(); searchresults.Count = azuresearchresult.Count; searchresults.Returned = azuresearchresult.Results.Count(); if ((skip + top) >= azuresearchresult.Count) { searchresults.Remaining = 0; } else { searchresults.Remaining = Convert.ToInt32(azuresearchresult.Count) - (skip + top); } if (skip >= searchresults.Count) { searchresults.Range = null; } else if (searchresults.Returned == 0) { searchresults.Range = null; } else { searchresults.Range = (skip + 1) + "-" + (skip + searchresults.Returned); } searchresults.ContinuationToken = azuresearchresult.ContinuationToken; searchresults.Facets = azuresearchresult.Facets; searchresults.Coverage = azuresearchresult.Coverage; searchresults.Results = new List <Models.Search.Result>(); foreach (Microsoft.Azure.Search.Models.SearchResult azureresult in azuresearchresult.Results) { var result = new Models.Search.Result(); result.Score = azureresult.Score; result.Document = azureresult.Document; //result.Images = new List<dynamic>(); //result.Images = new System.Dynamic.ExpandoObject(); result.Images = Dynamics.Images.BuildDynamicImagesListForJson(account.AccountNameKey, "product", azureresult.Document["id"].ToString(), listingImagesOnly); searchresults.Results.Add(result); } #endregion return(searchresults); }
public static IDictionary <string, object> TransformDynamicProductDetailsForJson(Models.Search.Result searchResult) { IDictionary <string, object> product = new System.Dynamic.ExpandoObject(); product = searchResult.Document; product = LocationResultsTransforms.TransformLocationResults(product); product["images"] = searchResult.Images; return(product); }
public JsonNetResult SearchProducts(string text, string filter = null, string orderBy = "relevance", int skip = 0, int top = 50, bool locationSort = false, string locationSortString = null) { //ProductResults productResults = null; //List<ProductDocumentModel> products = null; //dynamic products = null; DocumentSearchResult azuresearchresult = null; //var accountId = AuthenticationCookieManager.GetAuthenticationCookie().AccountID.ToString(); var accountNameKey = Common.GetSubDomain(Request.Url).ToLower(); Account account = Common.GetAccountObject(accountNameKey); if (account != null) { //Get client for this accounts search index //var accountSearchIndex = CoreServices.SearchServiceQueryClient.Indexes.GetClient(account.ProductSearchIndex); //Get search partition for this account, create client and connect to index: //Get from cache first var accountSearchIndex = Common.SearchIndexCache[account.ProductSearchIndex] as ISearchIndexClient; if (accountSearchIndex == null) { //Not in cache, create: ---------------------------- if (CoreServices.PlatformSettings.SearchParitions == null || CoreServices.PlatformSettings.SearchParitions.ToList().Count == 0) { //No Search Partitions Available in Static List, refresh list from Core Services Common.RefreshPlatformSettings(); } var searchPartition = CoreServices.PlatformSettings.SearchParitions.FirstOrDefault(partition => partition.Name == account.SearchPartition); if (searchPartition == null) { //May be a new partition, refresh platform setting and try again Common.RefreshPlatformSettings(); searchPartition = CoreServices.PlatformSettings.SearchParitions.FirstOrDefault(partition => partition.Name == account.SearchPartition); } var searchServiceClient = new SearchServiceClient(searchPartition.Name, new SearchCredentials(searchPartition.Key)); accountSearchIndex = searchServiceClient.Indexes.GetClient(account.ProductSearchIndex); //Store in cache: --------------------- Common.SearchIndexCache.Set(account.ProductSearchIndex, accountSearchIndex, new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(Common.SearchIndexClientCacheTimeInMinutes) }); } //Prepare the query var searchParameters = new SearchParameters(); //Assign filters searchParameters.Filter = filter; searchParameters.OrderBy = new List <string>(); //Add location sorting first (always supercedes others) if applicable if (locationSort) { //include location sorting //if (locationSortType == "point") //{ searchParameters.OrderBy.Add(locationSortString); //} //else if (locationSortType == "bounds") //{ //} } if (orderBy.ToLower() != "relevance") { var orderByList = orderBy.Split(','); foreach (string orderByItem in orderByList) { searchParameters.OrderBy.Add(orderByItem); } //Orderby Format: 'categoryNameKey asc' (relevance = 'search.Score asc') } searchParameters.Skip = skip; searchParameters.Top = top; searchParameters.IncludeTotalResultCount = true; //build strings to search against: //TO DO: //If the query contains dashes and no spaces, wrap it in quotes in order to get GUIDS and SKUS (The indexer replaces "-" with " " when storing into search) try { if (text.Contains("-")) { if (!text.Contains(" ")) { text = "\"" + text + "\""; } } } catch { } //Perform the search //NOTE: We add a wildcard at the end to get better results from text searches azuresearchresult = accountSearchIndex.Documents.Search(text + "*", searchParameters); //accountSearchIndex.b //azuresearchresult = Common.SearchIndexes.FirstOrDefault(i => i.IndexName == "").SearchIndexClient.Documents.Search(text + "*", searchParameters); //Common.SearchIndexes["IndexName"].Documents.Search(text + "*", searchParameters); } else { //Could not resolve Account } #region Loop through each search result, transform into SearchResult object and append associated 'Listing' type ImageRecords to each results var searchresults = new Models.Search.SearchResults(); searchresults.Count = azuresearchresult.Count; searchresults.Returned = azuresearchresult.Results.Count(); if ((skip + top) >= azuresearchresult.Count) { searchresults.Remaining = 0; } else { searchresults.Remaining = Convert.ToInt32(azuresearchresult.Count) - (skip + top); } if (skip >= searchresults.Count) { searchresults.Range = null; } else if (searchresults.Returned == 0) { searchresults.Range = null; } else { searchresults.Range = (skip + 1) + "-" + (skip + searchresults.Returned); } searchresults.ContinuationToken = azuresearchresult.ContinuationToken; searchresults.Facets = azuresearchresult.Facets; searchresults.Coverage = azuresearchresult.Coverage; searchresults.Results = new List <Models.Search.Result>(); foreach (Microsoft.Azure.Search.Models.SearchResult azureresult in azuresearchresult.Results) { var result = new Models.Search.Result(); result.Score = azureresult.Score; result.Document = azureresult.Document; //result.Images = new List<dynamic>(); result.Images = new System.Dynamic.ExpandoObject(); //Get all listing image records for this product id var imageRecordGroups = ImageRecordsCommon.GetImageRecordsForObject(accountNameKey, account.StoragePartition, "product", azureresult.Document["id"].ToString(), true); //<--Listing images ONLY! foreach (ImageRecordGroupModel imageRecordGroup in imageRecordGroups) { IDictionary <string, object> dynamicImageGroup = new System.Dynamic.ExpandoObject(); //List<IDictionary<string, object>> dynamicImageRecords = new List<IDictionary<string, object>>(); foreach (ImageRecordModel imageRecord in imageRecordGroup.ImageRecords) { //IDictionary<string, object> dynamicImageRecord = new System.Dynamic.ExpandoObject(); IDictionary <string, object> dynamicImageRecordProperties = new System.Dynamic.ExpandoObject(); //Since this is ONLY for listings we can ignore creating arrays for gallery image results #region Not needed since this is ALWAYS ONLY listings Look at API version to get LATEST code /* * if (imageRecord.Type == "gallery" && imageRecord.GalleryImages != null) * { * //dynamicImageRecordProperties["urls"] = imageRecord.GalleryImages; * * List<IDictionary<string, object>> galleryImages = new List<IDictionary<string, object>>(); * * foreach (ImageRecordGalleryModel galleryItem in imageRecord.GalleryImages) * { * IDictionary<string, object> galleryImage = new System.Dynamic.ExpandoObject(); * * galleryImage["url"] = galleryItem.Url; * galleryImage["title"] = galleryItem.Title; * galleryImage["description"] = galleryItem.Description; * galleryImage["filename"] = galleryItem.FileName; * * galleryImages.Add(galleryImage); * * } * * dynamicImageRecordProperties["images"] = galleryImages; * } * else * { * dynamicImageRecordProperties["url"] = imageRecord.Url; * dynamicImageRecordProperties["title"] = imageRecord.Title; * dynamicImageRecordProperties["description"] = imageRecord.Description; * dynamicImageRecordProperties["filename"] = imageRecord.FileName; * }*/ #endregion dynamicImageRecordProperties["url"] = imageRecord.Url; dynamicImageRecordProperties["title"] = imageRecord.Title; dynamicImageRecordProperties["description"] = imageRecord.Description; dynamicImageRecordProperties["height"] = imageRecord.Height; dynamicImageRecordProperties["width"] = imageRecord.Width; dynamicImageRecordProperties["formatname"] = imageRecord.FormatName; dynamicImageRecordProperties["formatkey"] = imageRecord.FormatNameKey; dynamicImageRecordProperties["filepath"] = imageRecord.FilePath; dynamicImageRecordProperties["filename"] = imageRecord.FileName; //dynamicImageRecord[imageRecord.FormatNameKey] = dynamicImageRecordProperties; if (!((IDictionary <String, object>)result.Images).ContainsKey(imageRecordGroup.GroupNameKey)) { result.Images[imageRecordGroup.GroupNameKey] = new System.Dynamic.ExpandoObject(); } ((IDictionary <String, Object>)(result.Images[imageRecordGroup.GroupNameKey]))[imageRecord.FormatNameKey] = dynamicImageRecordProperties; //dynamicImageRecords.Add(dynamicImageRecord); } //result.Images[imageRecordGroup.GroupNameKey] = dynamicImageRecords; } searchresults.Results.Add(result); } #endregion JsonNetResult jsonNetResult = new JsonNetResult(); jsonNetResult.Formatting = Newtonsoft.Json.Formatting.Indented; jsonNetResult.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local; //<-- Convert UTC times to LocalTime jsonNetResult.Data = searchresults; return(jsonNetResult); }