private IEnumerable<moduleModel.CatalogProduct> Search(CatalogIndexedSearchCriteria criteria, out CatalogItemSearchResults results, moduleModel.ItemResponseGroup responseGroup) { var items = new List<moduleModel.CatalogProduct>(); var itemsOrderedList = new List<string>(); var foundItemCount = 0; var dbItemCount = 0; var searchRetry = 0; //var myCriteria = criteria.Clone(); var myCriteria = criteria; do { // Search using criteria, it will only return IDs of the items var scope = _searchConnection.Scope; var searchResults = _searchProvider.Search(scope, criteria) as SearchResults; var itemKeyValues = searchResults.GetKeyAndOutlineFieldValueMap<string>(); results = new CatalogItemSearchResults(myCriteria, itemKeyValues, searchResults); searchRetry++; if (results.Items == null) { continue; } //Get only new found itemIds var uniqueKeys = results.Items.Keys.Except(itemsOrderedList).ToArray(); foundItemCount = uniqueKeys.Length; if (!results.Items.Any()) { continue; } itemsOrderedList.AddRange(uniqueKeys); // Now load items from repository var currentItems = _itemService.GetByIds(uniqueKeys.ToArray(), responseGroup); 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 && results.Items.Any() && searchRetry <= 3 && (myCriteria.RecordsToRetrieve + myCriteria.StartingRecord) < results.TotalCount); return items; }
public void Can_find_item_lucene() { var scope = "default"; var queryBuilder = new LuceneSearchQueryBuilder(); var conn = new SearchConnection(_LuceneStorageDir, scope); var provider = new LuceneSearchProvider(queryBuilder, conn); if (Directory.Exists(_LuceneStorageDir)) { Directory.Delete(_LuceneStorageDir, true); } SearchHelper.CreateSampleIndex(provider, scope); var criteria = new CatalogIndexedSearchCriteria { SearchPhrase = "product", IsFuzzySearch = true, Catalog = "goods", RecordsToRetrieve = 10, StartingRecord = 0, Pricelists = new string[] { } }; var results = provider.Search(scope, criteria); Assert.True(results.DocCount == 1, String.Format("Returns {0} instead of 1", results.DocCount)); criteria = new CatalogIndexedSearchCriteria { SearchPhrase = "sample product ", IsFuzzySearch = true, Catalog = "goods", RecordsToRetrieve = 10, StartingRecord = 0, Pricelists = new string[] { } }; results = provider.Search(scope, criteria); Assert.True(results.DocCount == 1, String.Format("\"Sample Product\" search returns {0} instead of 1", results.DocCount)); Directory.Delete(_LuceneStorageDir, true); }
public moduleModel.SearchResult SearchItems(CatalogIndexedSearchCriteria criteria, moduleModel.ItemResponseGroup responseGroup) { CatalogItemSearchResults results; var items = Search(criteria, out results, responseGroup); var response = new moduleModel.SearchResult(); response.Products.AddRange(items); response.ProductsTotalCount = results.TotalCount; // TODO need better way to find applied filter values var appliedFilters = criteria.CurrentFilters.SelectMany(x => x.GetValues()).Select(x => x.Id).ToArray(); if (results.FacetGroups != null) { response.Aggregations = results.FacetGroups.Select(g => g.ToModuleModel(appliedFilters)).ToArray(); } return response; }
public ProductSearchResult SearchItems(CatalogIndexedSearchCriteria criteria, moduleModel.ItemResponseGroup responseGroup = moduleModel.ItemResponseGroup.ItemSmall) { CatalogItemSearchResults results; var items = Search(criteria, out results, responseGroup); var catalogItems = new List<Product>(); // go through items foreach (var item in items) { var searchTags = results.Items[item.Id.ToLower()]; var currentOutline = this.GetItemOutlineUsingContext( searchTags[criteria.OutlineField].ToString(), criteria.Catalog); var catalogItem = item.ToWebModel(_blobUrlResolver) as Product; catalogItem.Outline = this.StripCatalogFromOutline(currentOutline, criteria.Catalog); int reviewTotal; if (searchTags.ContainsKey(criteria.ReviewsTotalField) && int.TryParse(searchTags[criteria.ReviewsTotalField].ToString(), out reviewTotal)) { catalogItem.ReviewsTotal = reviewTotal; } double reviewAvg; if (searchTags.ContainsKey(criteria.ReviewsAverageField) && double.TryParse(searchTags[criteria.ReviewsAverageField].ToString(), out reviewAvg)) { catalogItem.Rating = reviewAvg; } catalogItems.Add(catalogItem); } var response = new ProductSearchResult(); response.Items.AddRange(catalogItems); response.TotalCount = results.TotalCount; //TODO need better way to find applied filter values var appliedFilters = criteria.CurrentFilters.SelectMany(x => x.GetValues()).Select(x => x.Id).ToArray(); response.Facets = results.FacetGroups == null ? null : results.FacetGroups.Select(g => g.ToWebModel(appliedFilters)).ToArray(); return response; }
public IHttpActionResult Search(string store, string[] priceLists, [ModelBinder(typeof(SearchParametersBinder))] SearchParameters parameters, [FromUri] coreModel.ItemResponseGroup responseGroup = coreModel.ItemResponseGroup.ItemMedium, [FromUri] string outline = "", string language = "en-us", string currency = "USD") { var context = new Dictionary<string, object> { { "StoreId", store }, }; var fullLoadedStore = GetStoreById(store); if (fullLoadedStore == null) { throw new NullReferenceException(store + " not found"); } var catalog = fullLoadedStore.Catalog; string categoryId = null; var criteria = new CatalogIndexedSearchCriteria { Locale = language, Catalog = catalog.ToLowerInvariant() }; if (!string.IsNullOrWhiteSpace(outline)) { criteria.Outlines.Add(String.Format("{0}/{1}*", catalog, outline)); categoryId = outline.Split(new[] { '/' }).Last(); context.Add("CategoryId", categoryId); } #region Filters // Now fill in filters var filters = _browseFilterService.GetFilters(context); // Add all filters foreach (var filter in filters) { criteria.Add(filter); } // apply terms if (parameters.Terms != null && parameters.Terms.Count > 0) { foreach (var term in parameters.Terms) { var filter = filters.SingleOrDefault(x => x.Key.Equals(term.Key, StringComparison.OrdinalIgnoreCase) && (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(currency, StringComparison.OrdinalIgnoreCase))); var appliedFilter = _browseFilterService.Convert(filter, term.Value); criteria.Apply(appliedFilter); } } #endregion #region Facets // apply facet filters var facets = parameters.Facets; if (facets.Count != 0) { foreach (var key in facets.Keys) { var filter = filters.SingleOrDefault( x => x.Key.Equals(key, StringComparison.OrdinalIgnoreCase) && (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(currency, StringComparison.OrdinalIgnoreCase))); var appliedFilter = _browseFilterService.Convert(filter, facets[key]); criteria.Apply(appliedFilter); } } #endregion //criteria.ClassTypes.Add("Product"); criteria.RecordsToRetrieve = parameters.PageSize == 0 ? 10 : parameters.PageSize; criteria.StartingRecord = parameters.StartingRecord; criteria.Pricelists = priceLists; criteria.Currency = currency; criteria.StartDateFrom = parameters.StartDateFrom; criteria.SearchPhrase = parameters.FreeSearch; #region sorting if (!string.IsNullOrEmpty(parameters.Sort)) { var isDescending = "desc".Equals(parameters.SortOrder, StringComparison.OrdinalIgnoreCase); SearchSort sortObject = null; switch (parameters.Sort.ToLowerInvariant()) { case "price": if (criteria.Pricelists != null) { sortObject = new SearchSort( criteria.Pricelists.Select( priceList => new SearchSortField(String.Format("price_{0}_{1}", criteria.Currency.ToLower(), priceList.ToLower())) { IgnoredUnmapped = true, IsDescending = isDescending, DataType = SearchSortField.DOUBLE }) .ToArray()); } break; case "position": sortObject = new SearchSort( new SearchSortField(string.Format("sort{0}{1}", catalog, categoryId).ToLower()) { IgnoredUnmapped = true, IsDescending = isDescending }); break; case "name": sortObject = new SearchSort("name", isDescending); break; case "rating": sortObject = new SearchSort(criteria.ReviewsAverageField, isDescending); break; case "reviews": sortObject = new SearchSort(criteria.ReviewsTotalField, isDescending); break; default: sortObject = CatalogIndexedSearchCriteria.DefaultSortOrder; break; } criteria.Sort = sortObject; } #endregion //Load ALL products var searchResults = _browseService.SearchItems(criteria, responseGroup); // populate inventory if ((responseGroup & ItemResponseGroup.ItemProperties) == ItemResponseGroup.ItemProperties) { PopulateInventory(fullLoadedStore.FulfillmentCenter, searchResults.Items); } return this.Ok(searchResults); }
public IHttpActionResult Search([FromUri] ProductSearchRequest request) { request = request ?? new ProductSearchRequest(); request.Normalize(); var context = new Dictionary<string, object> { { "StoreId", request.Store }, }; var fullLoadedStore = GetStoreById(request.Store); if (fullLoadedStore == null) { throw new NullReferenceException(request.Store + " not found"); } var catalog = fullLoadedStore.Catalog; string categoryId = null; var criteria = new CatalogIndexedSearchCriteria { Locale = request.Language, Catalog = catalog.ToLowerInvariant(), IsFuzzySearch = true }; if (!string.IsNullOrWhiteSpace(request.Outline)) { criteria.Outlines.Add(string.Format("{0}/{1}*", catalog, request.Outline)); categoryId = request.Outline.Split(new[] { '/' }).Last(); context.Add("CategoryId", categoryId); } #region Filters // Now fill in filters var filters = _browseFilterService.GetFilters(context); // Add all filters foreach (var filter in filters) { criteria.Add(filter); } // apply terms var terms = ParseKeyValues(request.Terms); if (terms.Any()) { var filtersWithValues = filters .Where(x => (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(request.Currency, StringComparison.OrdinalIgnoreCase))) .Select(x => new { Filter = x, Values = x.GetValues() }) .ToList(); foreach (var term in terms) { var filter = filters.SingleOrDefault(x => x.Key.Equals(term.Key, StringComparison.OrdinalIgnoreCase) && (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(request.Currency, StringComparison.OrdinalIgnoreCase))); // handle special filter term with a key = "tags", it contains just values and we need to determine which filter to use if (filter == null && term.Key == "tags") { foreach (var termValue in term.Values) { // try to find filter by value var foundFilter = filtersWithValues.FirstOrDefault(x => x.Values.Any(y => y.Id.Equals(termValue))); if (foundFilter != null) { filter = foundFilter.Filter; var appliedFilter = _browseFilterService.Convert(filter, term.Values); criteria.Apply(appliedFilter); } } } else { var appliedFilter = _browseFilterService.Convert(filter, term.Values); criteria.Apply(appliedFilter); } } } #endregion #region Facets // apply facet filters var facets = ParseKeyValues(request.Facets); foreach (var facet in facets) { var filter = filters.SingleOrDefault( x => x.Key.Equals(facet.Key, StringComparison.OrdinalIgnoreCase) && (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(request.Currency, StringComparison.OrdinalIgnoreCase))); var appliedFilter = _browseFilterService.Convert(filter, facet.Values); criteria.Apply(appliedFilter); } #endregion //criteria.ClassTypes.Add("Product"); criteria.RecordsToRetrieve = request.Take <= 0 ? 10 : request.Take; criteria.StartingRecord = request.Skip; criteria.Pricelists = request.Pricelists; criteria.Currency = request.Currency; criteria.StartDateFrom = request.StartDateFrom; criteria.SearchPhrase = request.SearchPhrase; #region sorting if (!string.IsNullOrEmpty(request.Sort)) { var isDescending = "desc".Equals(request.SortOrder, StringComparison.OrdinalIgnoreCase); SearchSort sortObject = null; switch (request.Sort.ToLowerInvariant()) { case "price": if (criteria.Pricelists != null) { sortObject = new SearchSort( criteria.Pricelists.Select( priceList => new SearchSortField(String.Format("price_{0}_{1}", criteria.Currency.ToLower(), priceList.ToLower())) { IgnoredUnmapped = true, IsDescending = isDescending, DataType = SearchSortField.DOUBLE }) .ToArray()); } break; case "position": sortObject = new SearchSort( new SearchSortField(string.Format("sort{0}{1}", catalog, categoryId).ToLower()) { IgnoredUnmapped = true, IsDescending = isDescending }); break; case "name": sortObject = new SearchSort("name", isDescending); break; case "rating": sortObject = new SearchSort(criteria.ReviewsAverageField, isDescending); break; case "reviews": sortObject = new SearchSort(criteria.ReviewsTotalField, isDescending); break; default: sortObject = CatalogIndexedSearchCriteria.DefaultSortOrder; break; } criteria.Sort = sortObject; } #endregion //Load ALL products var searchResults = _browseService.SearchItems(criteria, request.ResponseGroup); // populate inventory if ((request.ResponseGroup & ItemResponseGroup.ItemProperties) == ItemResponseGroup.ItemProperties) { PopulateInventory(fullLoadedStore.FulfillmentCenter, searchResults.Items); } return Ok(searchResults); }
private SearchResult SearchProducts(SearchCriteria criteria) { var context = new Dictionary<string, object> { { "StoreId", criteria.StoreId }, }; var store = _storeService.GetById(criteria.StoreId); if (store == null) { throw new NullReferenceException("Cannot find store '" + criteria.StoreId + "'"); } var catalog = store.Catalog; var categoryId = criteria.CategoryId; var serviceCriteria = new CatalogIndexedSearchCriteria { Locale = criteria.LanguageCode, Catalog = catalog.ToLowerInvariant(), IsFuzzySearch = true, }; if (!string.IsNullOrWhiteSpace(criteria.Outline)) { serviceCriteria.Outlines.Add(string.Format(CultureInfo.InvariantCulture, "{0}/{1}*", catalog, criteria.Outline)); categoryId = criteria.Outline.Split('/').Last(); } else { if (!string.IsNullOrEmpty(categoryId)) { serviceCriteria.Outlines.Add(string.Format(CultureInfo.InvariantCulture, "{0}/{1}*", catalog, categoryId)); } } if (!string.IsNullOrEmpty(categoryId)) { context.Add("CategoryId", categoryId); } #region Filters // Now fill in filters var filters = _browseFilterService.GetFilters(context); // Add all filters foreach (var filter in filters) { serviceCriteria.Add(filter); } // apply terms var terms = ParseKeyValues(criteria.Terms); if (terms.Any()) { var filtersWithValues = filters .Where(x => (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(criteria.Currency, StringComparison.OrdinalIgnoreCase))) .Select(x => new { Filter = x, Values = x.GetValues() }) .ToList(); foreach (var term in terms) { var filter = filters.SingleOrDefault(x => x.Key.Equals(term.Key, StringComparison.OrdinalIgnoreCase) && (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(criteria.Currency, StringComparison.OrdinalIgnoreCase))); // handle special filter term with a key = "tags", it contains just values and we need to determine which filter to use if (filter == null && term.Key == "tags") { foreach (var termValue in term.Values) { // try to find filter by value var foundFilter = filtersWithValues.FirstOrDefault(x => x.Values.Any(y => y.Id.Equals(termValue))); if (foundFilter != null) { filter = foundFilter.Filter; var appliedFilter = _browseFilterService.Convert(filter, term.Values); serviceCriteria.Apply(appliedFilter); } } } else { var appliedFilter = _browseFilterService.Convert(filter, term.Values); serviceCriteria.Apply(appliedFilter); } } } #endregion #region Facets // apply facet filters var facets = ParseKeyValues(criteria.Facets); foreach (var facet in facets) { var filter = filters.SingleOrDefault( x => x.Key.Equals(facet.Key, StringComparison.OrdinalIgnoreCase) && (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(criteria.Currency, StringComparison.OrdinalIgnoreCase))); var appliedFilter = _browseFilterService.Convert(filter, facet.Values); serviceCriteria.Apply(appliedFilter); } #endregion //criteria.ClassTypes.Add("Product"); serviceCriteria.RecordsToRetrieve = criteria.Take <= 0 ? 10 : criteria.Take; serviceCriteria.StartingRecord = criteria.Skip; serviceCriteria.Pricelists = criteria.PricelistIds; serviceCriteria.Currency = criteria.Currency; serviceCriteria.StartDateFrom = criteria.StartDateFrom; serviceCriteria.SearchPhrase = criteria.Keyword; #region sorting if (!string.IsNullOrEmpty(criteria.Sort)) { var isDescending = "desc".Equals(criteria.SortOrder, StringComparison.OrdinalIgnoreCase); SearchSort sortObject = null; switch (criteria.Sort.ToLowerInvariant()) { case "price": if (serviceCriteria.Pricelists != null) { sortObject = new SearchSort( serviceCriteria.Pricelists.Select( priceList => new SearchSortField(String.Format("price_{0}_{1}", serviceCriteria.Currency.ToLower(), priceList.ToLower())) { IgnoredUnmapped = true, IsDescending = isDescending, DataType = SearchSortField.DOUBLE }) .ToArray()); } break; case "position": sortObject = new SearchSort( new SearchSortField(string.Concat("sort", catalog, categoryId).ToLower()) { IgnoredUnmapped = true, IsDescending = isDescending }); break; case "name": sortObject = new SearchSort("name", isDescending); break; case "rating": sortObject = new SearchSort(serviceCriteria.ReviewsAverageField, isDescending); break; case "reviews": sortObject = new SearchSort(serviceCriteria.ReviewsTotalField, isDescending); break; default: sortObject = CatalogIndexedSearchCriteria.DefaultSortOrder; break; } serviceCriteria.Sort = sortObject; } #endregion var responseGroup = ItemResponseGroup.ItemInfo | ItemResponseGroup.ItemAssets | ItemResponseGroup.Seo; if ((criteria.ResponseGroup & SearchResponseGroup.WithProperties) == SearchResponseGroup.WithProperties) { responseGroup |= ItemResponseGroup.ItemProperties; } if ((criteria.ResponseGroup & SearchResponseGroup.WithVariations) == SearchResponseGroup.WithVariations) { responseGroup |= ItemResponseGroup.Variations; } //Load ALL products var searchResults = _browseService.SearchItems(serviceCriteria, responseGroup); // populate inventory //if ((request.ResponseGroup & ItemResponseGroup.ItemProperties) == ItemResponseGroup.ItemProperties) if ((criteria.ResponseGroup & SearchResponseGroup.WithProperties) == SearchResponseGroup.WithProperties) { PopulateInventory(store.FulfillmentCenter, searchResults.Products); } return searchResults; }
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { if (bindingContext.ModelType != typeof(CatalogIndexedSearchCriteria)) { return false; } var key = actionContext.Request.RequestUri.Query; var qs = HttpUtility.ParseQueryString(key); var qsDict = this.NvToDict(qs); // parse facets var facets = qsDict.Where(k => FacetRegex.IsMatch(k.Key)) .Select(k => k.WithKey(FacetRegex.Replace(k.Key, ""))) .ToDictionary(x => x.Key, y => y.Value.Split(',')); // parse facets var terms = qsDict.Where(k => TermRegex.IsMatch(k.Key)) .Select(k => k.WithKey(TermRegex.Replace(k.Key, ""))) .ToDictionary(x => x.Key, y => y.Value.Split(',')); var result = new CatalogIndexedSearchCriteria { SearchPhrase = qs["q"].EmptyToNull(), RecordsToRetrieve = qs["take"].TryParse(20), StartingRecord = qs["skip"].TryParse(0), }; // apply filters if one specified if (terms.Count > 0) { foreach (var term in terms) { var termFilter = new AttributeFilter { Key = term.Key.ToLowerInvariant(), Values = term.Value.Select( x => new AttributeFilterValue() { Id = x.ToLowerInvariant(), Value = x.ToLowerInvariant() }).ToArray() }; result.Apply(termFilter); } } //result.ClassTypes.Add("Product"); var startDateFromStr = qs["startdatefrom"].EmptyToNull(); if (!string.IsNullOrWhiteSpace(startDateFromStr)) { DateTime startDateFrom; if (DateTime.TryParse(startDateFromStr, out startDateFrom)) { result.StartDateFrom = startDateFrom; } } //TODO load pricelists result.Pricelists = null; result.Currency = qs["curreny"].EmptyToNull(); var sortQuery = qs["sort"].EmptyToNull(); var sort = string.IsNullOrEmpty(sortQuery) ? "name" : sortQuery; var sortOrder = qs["sortorder"].EmptyToNull(); var outline = qs["outline"].EmptyToNull(); var isDescending = "desc".Equals(sortOrder, StringComparison.OrdinalIgnoreCase); var catalogId = actionContext.ActionArguments.ContainsKey("catalog") ? actionContext.ActionArguments["catalog"] : null; string categoryId = null; if (!string.IsNullOrWhiteSpace(outline)) { categoryId = outline.Split(new[] { '/' }).Last(); } SearchSort sortObject = null; switch (sort.ToLowerInvariant()) { case "price": if (result.Pricelists != null) { sortObject = new SearchSort( result.Pricelists.Select( priceList => new SearchSortField( String.Format( "price_{0}_{1}", result.Currency.ToLower(), priceList.ToLower())) { IgnoredUnmapped = true, IsDescending = isDescending, DataType = SearchSortField.DOUBLE }) .ToArray()); } break; case "position": sortObject = new SearchSort( new SearchSortField(string.Format("sort{0}{1}", catalogId, categoryId).ToLower()) { IgnoredUnmapped = true, IsDescending = isDescending }); break; case "name": sortObject = new SearchSort("name", isDescending); break; case "rating": sortObject = new SearchSort(result.ReviewsAverageField, isDescending); break; case "reviews": sortObject = new SearchSort(result.ReviewsTotalField, isDescending); break; default: sortObject = CatalogIndexedSearchCriteria.DefaultSortOrder; break; } result.Sort = sortObject; //Use fuzzy search to allow spelling error tolerance result.IsFuzzySearch = true; bindingContext.Model = result; return true; }
protected void AddQueryString(BoolQuery<ESDocument> query, CatalogIndexedSearchCriteria filter, params string[] fields) { var searchPhrase = filter.SearchPhrase; if (filter.IsFuzzySearch) { query.Must( q => q.MultiMatch( x => x.Fields(fields).Operator(Operator.AND).Fuzziness(filter.FuzzyMinSimilarity).Query(searchPhrase))); } else { query.Must( q => q.MultiMatch( x => x.Fields(fields).Operator(Operator.AND).Query(searchPhrase))); } }
public void Can_get_item_facets_lucene() { var scope = "default"; var queryBuilder = new LuceneSearchQueryBuilder(); var conn = new SearchConnection(_LuceneStorageDir, scope); var provider = new LuceneSearchProvider(queryBuilder, conn); Debug.WriteLine("Lucene connection: {0}", conn.ToString()); if (Directory.Exists(_LuceneStorageDir)) { Directory.Delete(_LuceneStorageDir, true); } SearchHelper.CreateSampleIndex(provider, scope); var criteria = new CatalogIndexedSearchCriteria { SearchPhrase = "", IsFuzzySearch = true, Catalog = "goods", RecordsToRetrieve = 10, StartingRecord = 0, Currency = "USD", Pricelists = new[] { "default" } }; var filter = new AttributeFilter { Key = "Color" }; filter.Values = new[] { new AttributeFilterValue { Id = "red", Value = "red" }, new AttributeFilterValue { Id = "blue", Value = "blue" }, new AttributeFilterValue { Id = "black", Value = "black" } }; var rangefilter = new RangeFilter { Key = "size" }; rangefilter.Values = new[] { new RangeFilterValue { Id = "0_to_5", Lower = "0", Upper = "5" }, new RangeFilterValue { Id = "5_to_10", Lower = "5", Upper = "10" } }; var priceRangefilter = new PriceRangeFilter { Currency = "usd" }; priceRangefilter.Values = new[] { new RangeFilterValue { Id = "0_to_100", Lower = "0", Upper = "100" }, new RangeFilterValue { Id = "100_to_700", Lower = "100", Upper = "700" } }; criteria.Add(filter); criteria.Add(rangefilter); criteria.Add(priceRangefilter); var results = provider.Search(scope, criteria); Assert.True(results.DocCount == 4, String.Format("Returns {0} instead of 4", results.DocCount)); var redCount = GetFacetCount(results, "Color", "red"); Assert.True(redCount == 2, String.Format("Returns {0} facets of red instead of 2", redCount)); var priceCount = GetFacetCount(results, "Price", "0_to_100"); Assert.True(priceCount == 2, String.Format("Returns {0} facets of 0_to_100 prices instead of 2", priceCount)); var priceCount2 = GetFacetCount(results, "Price", "100_to_700"); Assert.True(priceCount2 == 2, String.Format("Returns {0} facets of 100_to_700 prices instead of 2", priceCount2)); var sizeCount = GetFacetCount(results, "size", "0_to_5"); Assert.True(sizeCount == 2, String.Format("Returns {0} facets of 0_to_5 size instead of 2", sizeCount)); var sizeCount2 = GetFacetCount(results, "size", "5_to_10"); Assert.True(sizeCount2 == 1, String.Format("Returns {0} facets of 5_to_10 size instead of 1", sizeCount2)); // only 1 result because upper bound is not included var outlineCount = results.Documents[0].Documents[0]["__outline"].Values.Count(); Assert.True(outlineCount == 2, String.Format("Returns {0} outlines instead of 2", outlineCount)); Directory.Delete(_LuceneStorageDir, true); }
public void Can_get_item_multiple_filters_lucene() { var scope = "default"; var queryBuilder = new LuceneSearchQueryBuilder(); var conn = new SearchConnection(_LuceneStorageDir, scope); var provider = new LuceneSearchProvider(queryBuilder, conn); Debug.WriteLine("Lucene connection: {0}", conn.ToString()); if (Directory.Exists(_LuceneStorageDir)) { Directory.Delete(_LuceneStorageDir, true); } SearchHelper.CreateSampleIndex(provider, scope); var criteria = new CatalogIndexedSearchCriteria { SearchPhrase = "", IsFuzzySearch = true, Catalog = "goods", RecordsToRetrieve = 10, StartingRecord = 0, Currency = "USD", Pricelists = new[] { "default" } }; var colorFilter = new AttributeFilter { Key = "Color" }; colorFilter.Values = new[] { new AttributeFilterValue { Id = "red", Value = "red" }, new AttributeFilterValue { Id = "blue", Value = "blue" }, new AttributeFilterValue { Id = "black", Value = "black" } }; var filter = new AttributeFilter { Key = "Color" }; filter.Values = new[] { new AttributeFilterValue { Id = "black", Value = "black" } }; var rangefilter = new RangeFilter { Key = "size" }; rangefilter.Values = new[] { new RangeFilterValue { Id = "0_to_5", Lower = "0", Upper = "5" }, new RangeFilterValue { Id = "5_to_10", Lower = "5", Upper = "11" } }; var priceRangefilter = new PriceRangeFilter { Currency = "usd" }; priceRangefilter.Values = new[] { new RangeFilterValue { Id = "100_to_700", Lower = "100", Upper = "700" } }; criteria.Add(colorFilter); criteria.Add(priceRangefilter); // add applied filters criteria.Apply(filter); //criteria.Apply(rangefilter); //criteria.Apply(priceRangefilter); var results = provider.Search(scope, criteria); var blackCount = GetFacetCount(results, "Color", "black"); Assert.True(blackCount == 1, String.Format("Returns {0} facets of black instead of 2", blackCount)); //Assert.True(results.DocCount == 1, String.Format("Returns {0} instead of 1", results.DocCount)); Directory.Delete(_LuceneStorageDir, true); }