Exemple #1
0
        /// <summary>
        /// Creates the data model.
        /// </summary>
        /// <param name="criteria">The criteria.</param>
        /// <param name="parameters">The parameters.</param>
        /// <param name="cacheResults">if set to <c>true</c> [cache results].</param>
        /// <returns>CatalogItemSearchModel.</returns>
        private CatalogItemSearchModel CreateDataModel(CatalogItemSearchCriteria criteria, SearchParameters parameters,
                                                       bool cacheResults)
        {
            var session = UserHelper.CustomerSession;

            // Create a model
            var dataSource = new CatalogItemSearchModel();

            // Now fill in filters
            var filters = _searchFilter.Filters;

            // Add all filters
            foreach (var filter in filters)
            {
                criteria.Add(filter);
            }

            // Get selected filters
            var facets = parameters.Facets;

            dataSource.SelectedFilters = new List <SelectedFilterModel>();
            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(StoreHelper.CustomerSession.Currency, StringComparison.OrdinalIgnoreCase)));

                    var appliedFilter = _searchFilter.Convert(filter, facets[key]);

                    foreach (var val in appliedFilter.GetValues())
                    {
                        criteria.Apply(appliedFilter);
                        dataSource.SelectedFilters.Add(
                            new SelectedFilterModel(_searchFilter.Convert(filter), _searchFilter.Convert(val)));
                    }
                }
            }

            // Perform search
            var sort      = string.IsNullOrEmpty(parameters.Sort) ? "position" : parameters.Sort;
            var sortOrder = parameters.SortOrder;

            var isDescending = "desc".Equals(sortOrder, StringComparison.OrdinalIgnoreCase);

            SearchSort sortObject = null;

            switch (sort.ToLowerInvariant())
            {
            case "price":
                if (session.Pricelists != null)
                {
                    sortObject = new SearchSort(session.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}", session.CatalogId, session.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 = CatalogItemSearchCriteria.DefaultSortOrder;
                break;
            }

            criteria.Sort = sortObject;
            CatalogItemSearchResults results;
            // Search using criteria, it will only return IDs of the items
            var items         = Search(criteria, cacheResults, out results).ToArray();
            var itemsIdsArray = items.Select(i => i.ItemId).ToArray();

            // Now load items with appropriate
            var itemModelList = new List <CatalogItemWithPriceModel>();

            if (items.Any())
            {
                // Now convert it to the model
                var prices         = _priceListClient.GetLowestPrices(session.Pricelists, itemsIdsArray, 1);
                var availabilities = _catalogClient.GetItemAvailability(itemsIdsArray,
                                                                        UserHelper.StoreClient.GetCurrentStore().FulfillmentCenterId);

                foreach (var item in items)
                {
                    PriceModel            priceModel        = null;
                    ItemAvailabilityModel availabilityModel = null;
                    var searchTags = results.Items[item.ItemId.ToLower()];

                    var currentOutline = this.GetItemOutlineUsingContext(searchTags[criteria.OutlineField].ToString());

                    //Cache outline
                    HttpContext.Items["browsingoutline_" + item.ItemId.ToLower()] = StripCatalogFromOutline(currentOutline);

                    if (prices != null && prices.Any())
                    {
                        var lowestPrice = (prices.Where(p => p.ItemId.Equals(item.ItemId, StringComparison.OrdinalIgnoreCase))).SingleOrDefault();
                        if (lowestPrice != null)
                        {
                            var tags = new Hashtable
                            {
                                {
                                    "Outline",
                                    currentOutline
                                }
                            };
                            priceModel = _marketing.GetItemPriceModel(item, lowestPrice, tags);
                        }
                    }

                    if (availabilities != null && availabilities.Any())
                    {
                        var availability =
                            (from a in availabilities
                             where a.ItemId.Equals(item.ItemId, StringComparison.OrdinalIgnoreCase)
                             select a).SingleOrDefault();

                        availabilityModel = new ItemAvailabilityModel(availability);
                    }

                    var itemModel = new CatalogItemWithPriceModel(CatalogHelper.CreateItemModel(item), priceModel, availabilityModel)
                    {
                        SearchOutline = currentOutline
                    };

                    try
                    {
                        itemModel.ItemReviewTotals.AverageRating = double.Parse(searchTags[criteria.ReviewsAverageField].ToString());
                        itemModel.ItemReviewTotals.TotalReviews  = int.Parse(searchTags[criteria.ReviewsTotalField].ToString());
                    }
                    catch
                    {
                        //There are no reviews indexed?
                    }
                    itemModelList.Add(itemModel);
                }
            }

            dataSource.FilterGroups = _searchFilter.Convert(results.FacetGroups);
            dataSource.CatalogItems = itemModelList.ToArray();
            dataSource.Criteria     = criteria;

            // Create pager
            var pager = new PagerModel
            {
                TotalCount            = results.TotalCount,
                CurrentPage           = criteria.StartingRecord / criteria.RecordsToRetrieve + 1,
                RecordsPerPage        = criteria.RecordsToRetrieve,
                StartingRecord        = criteria.StartingRecord,
                DisplayStartingRecord = criteria.StartingRecord + 1,
                SortValues            = new[] { "Position", "Name", "Price", "Rating", "Reviews" },
                SelectedSort          = sort,
                SortOrder             = isDescending ? "desc" : "asc"
            };

            var end = criteria.StartingRecord + criteria.RecordsToRetrieve;

            pager.DisplayEndingRecord = end > results.TotalCount ? results.TotalCount : end;

            dataSource.Pager = pager;
            return(dataSource);
        }
Exemple #2
0
        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 CatalogItemSearchCriteria
            {
                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_index_product_demo_data_and_search(string providerType)
        {
            var provider = GetSearchProvider(providerType, _scope);

            RebuildIndex(provider, CatalogItemSearchCriteria.DocType);

            // find all products in the category
            var criteria = new CatalogItemSearchCriteria
            {
                Catalog  = GetCatalogId("electronics"),
                Currency = "USD"
            };

            // Add facets
            var colorFacet = new AttributeFilter {
                Key = "color"
            };

            var brandFacet = new AttributeFilter
            {
                Key         = "brand",
                IsLocalized = true,
                Values      = new[]
                {
                    new AttributeFilterValue {
                        Id = "Apple", Value = "Apple"
                    },
                    new AttributeFilterValue {
                        Id = "Asus", Value = "Asus"
                    },
                    new AttributeFilterValue {
                        Id = "Samsung", Value = "Samsung"
                    }
                }
            };

            var sizeFacet = new RangeFilter
            {
                Key    = "display_size",
                Values = new[]
                {
                    new RangeFilterValue {
                        Id = "0_to_5", Lower = "0", Upper = "5"
                    },
                    new RangeFilterValue {
                        Id = "5_to_10", Lower = "5", Upper = "10"
                    }
                }
            };

            var priceFacet = new PriceRangeFilter
            {
                Currency = "USD",
                Values   = new[]
                {
                    new RangeFilterValue {
                        Id = "under-100", Upper = "100"
                    },
                    new RangeFilterValue {
                        Id = "200-600", Lower = "200", Upper = "600"
                    }
                }
            };

            criteria.Add(brandFacet);
            criteria.Add(colorFacet);
            criteria.Add(sizeFacet);
            criteria.Add(priceFacet);

            var ibs           = GetItemBrowsingService(provider);
            var searchResults = ibs.SearchItems(_scope, criteria, ItemResponseGroup.ItemLarge);

            Assert.True(searchResults.TotalCount > 0, $"Didn't find any products using {providerType} provider");
            Assert.True(searchResults.Aggregations.Any(), $"Didn't find any aggregations using {providerType} provider");

            Assert.True(GetFacetValuesCount(searchResults, "color") > 0, $"Didn't find any aggregation value for Color using {providerType} provider");

            Assert.Equal(0, GetFacetValue(searchResults, "brand", "Apple"));
            Assert.Equal(2, GetFacetValue(searchResults, "brand", "Asus"));
            Assert.Equal(5, GetFacetValue(searchResults, "brand", "Samsung"));

            criteria = new CatalogItemSearchCriteria {
                Currency = "USD", Locale = "en-us", SearchPhrase = "sony"
            };
            searchResults = ibs.SearchItems(_scope, criteria, ItemResponseGroup.ItemLarge);

            Assert.True(searchResults.TotalCount > 0);
        }
Exemple #4
0
        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 CatalogItemSearchCriteria
            {
                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);
        }
Exemple #5
0
        public void Can_index_product_demo_data_and_search(string providerType)
        {
            var scope    = "test";
            var provider = GetSearchProvider(providerType, scope);

            //if (provider is ElasticSearchProvider)
            //    (provider as ElasticSearchProvider).AutoCommitCount = 1; // commit every one document

            provider.RemoveAll(scope, "");
            var controller = GetSearchIndexController(provider);

            controller.RemoveIndex(scope, CatalogItemSearchCriteria.DocType);
            controller.BuildIndex(scope, CatalogItemSearchCriteria.DocType, x => { return; });


            // sleep for index to be commited
            Thread.Sleep(5000);

            // get catalog id by name
            var catalogRepo = GetCatalogRepository();
            var catalog     = catalogRepo.Catalogs.SingleOrDefault(x => x.Name.Equals("electronics", StringComparison.OrdinalIgnoreCase));

            // find all prodducts in the category
            var catalogCriteria = new CatalogItemSearchCriteria()
            {
                Catalog  = catalog.Id,
                Currency = "USD"
            };

            // Add all filters
            var brandFilter = new AttributeFilter {
                Key = "brand"
            };
            var filter = new AttributeFilter {
                Key = "color", IsLocalized = true
            };

            filter.Values = new[]
            {
                new AttributeFilterValue {
                    Id = "Red", Value = "Red"
                },
                new AttributeFilterValue {
                    Id = "Gray", Value = "Gray"
                },
                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 = "under-100", Upper = "100"
                },
                new RangeFilterValue {
                    Id = "200-600", Lower = "200", Upper = "600"
                }
            };

            catalogCriteria.Add(filter);
            catalogCriteria.Add(rangefilter);
            catalogCriteria.Add(priceRangefilter);
            catalogCriteria.Add(brandFilter);

            var ibs           = GetItemBrowsingService(provider);
            var searchResults = ibs.SearchItems(scope, catalogCriteria, Domain.Catalog.Model.ItemResponseGroup.ItemLarge);

            Assert.True(searchResults.TotalCount > 0, string.Format("Didn't find any products using {0} search", providerType));
            Assert.True(searchResults.Aggregations.Count() > 0, string.Format("Didn't find any aggregations using {0} search", providerType));

            var colorAggregation = searchResults.Aggregations.SingleOrDefault(a => a.Field.Equals("color", StringComparison.OrdinalIgnoreCase));

            Assert.True(colorAggregation.Items.Where(x => x.Value.ToString().Equals("Red", StringComparison.OrdinalIgnoreCase)).SingleOrDefault().Count == 6);
            Assert.True(colorAggregation.Items.Where(x => x.Value.ToString().Equals("Gray", StringComparison.OrdinalIgnoreCase)).SingleOrDefault().Count == 3);
            Assert.True(colorAggregation.Items.Where(x => x.Value.ToString().Equals("Black", StringComparison.OrdinalIgnoreCase)).SingleOrDefault().Count == 13);

            var brandAggregation = searchResults.Aggregations.SingleOrDefault(a => a.Field.Equals("brand", StringComparison.OrdinalIgnoreCase));

            Assert.True(brandAggregation.Items.Where(x => x.Value.ToString().Equals("Beats By Dr Dre", StringComparison.OrdinalIgnoreCase)).SingleOrDefault().Count == 3);

            var keywordSearchCriteria = new KeywordSearchCriteria(CatalogItemSearchCriteria.DocType)
            {
                Currency = "USD", Locale = "en-us", SearchPhrase = "sony"
            };

            searchResults = ibs.SearchItems(scope, keywordSearchCriteria, Domain.Catalog.Model.ItemResponseGroup.ItemLarge);
            Assert.True(searchResults.TotalCount > 0);
        }
Exemple #6
0
        public void Can_get_item_multiple_filters(string providerType)
        {
            var scope    = _DefaultScope;
            var provider = GetSearchProvider(providerType, scope);

            SearchHelper.CreateSampleIndex(provider, scope);

            var criteria = new CatalogItemSearchCriteria
            {
                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(rangefilter);
            criteria.Add(priceRangefilter);

            // add applied filters
            criteria.Apply(filter);
            criteria.Apply(rangefilter);
            criteria.Apply(priceRangefilter);

            var results = provider.Search <DocumentDictionary>(scope, criteria);

            var blackCount = GetFacetCount(results, "Color", "black");

            Assert.True(blackCount == 1, string.Format("Returns {0} facets of black instead of 1", blackCount));

            var redCount = GetFacetCount(results, "Color", "red");

            Assert.True(redCount == 2, string.Format("Returns {0} facets of black instead of 2", redCount));

            var priceCount = GetFacetCount(results, "Price", "100_to_700");

            Assert.True(priceCount == 1, string.Format("Returns {0} facets of 100_to_700 instead of 1", priceCount));

            Assert.True(results.DocCount == 1, string.Format("Returns {0} instead of 1", results.DocCount));
        }
Exemple #7
0
        public void Can_find_pricelists_prices(string providerType)
        {
            var scope    = _DefaultScope;
            var provider = GetSearchProvider(providerType, scope);

            SearchHelper.CreateSampleIndex(provider, scope);

            var criteria = new CatalogItemSearchCriteria
            {
                IsFuzzySearch     = true,
                Catalog           = "goods",
                RecordsToRetrieve = 10,
                StartingRecord    = 0,
                Currency          = "usd",
                Pricelists        = new string[] { "default", "sale" }
            };

            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(priceRangefilter);

            var results = provider.Search <DocumentDictionary>(scope, criteria);

            Assert.True(results.DocCount == 6, string.Format("Returns {0} instead of 6", results.DocCount));

            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 == 3, string.Format("Returns {0} facets of 100_to_700 prices instead of 3", priceCount2));

            criteria = new CatalogItemSearchCriteria
            {
                IsFuzzySearch     = true,
                Catalog           = "goods",
                RecordsToRetrieve = 10,
                StartingRecord    = 0,
                Currency          = "usd",
                Pricelists        = new string[] { "sale", "default" }
            };

            criteria.Add(priceRangefilter);

            results = provider.Search <DocumentDictionary>(scope, criteria);

            Assert.True(results.DocCount == 6, string.Format("\"Sample Product\" search returns {0} instead of 6", results.DocCount));

            var priceSaleCount = GetFacetCount(results, "Price", "0_to_100");

            Assert.True(priceSaleCount == 3, string.Format("Returns {0} facets of 0_to_100 prices instead of 2", priceSaleCount));

            var priceSaleCount2 = GetFacetCount(results, "Price", "100_to_700");

            Assert.True(priceSaleCount2 == 2, string.Format("Returns {0} facets of 100_to_700 prices instead of 3", priceSaleCount2));
        }
Exemple #8
0
        public void Can_get_item_facets(string providerType)
        {
            var scope    = _DefaultScope;
            var provider = GetSearchProvider(providerType, scope);

            SearchHelper.CreateSampleIndex(provider, scope);

            var criteria = new CatalogItemSearchCriteria
            {
                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"
                },
                new RangeFilterValue {
                    Id = "over_700", Lower = "700"
                },
                new RangeFilterValue {
                    Id = "under_100", Upper = "100"
                },
            };

            criteria.Add(filter);
            criteria.Add(rangefilter);
            criteria.Add(priceRangefilter);

            var results = provider.Search <DocumentDictionary>(scope, criteria);

            Assert.True(results.DocCount == 6, string.Format("Returns {0} instead of 6", results.DocCount));

            var redCount = GetFacetCount(results, "Color", "red");

            Assert.True(redCount == 3, string.Format("Returns {0} facets of red instead of 3", 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 == 3, string.Format("Returns {0} facets of 100_to_700 prices instead of 3", priceCount2));

            var priceCount3 = GetFacetCount(results, "Price", "over_700");

            Assert.True(priceCount3 == 1, string.Format("Returns {0} facets of over_700 prices instead of 1", priceCount3));

            var priceCount4 = GetFacetCount(results, "Price", "under_100");

            Assert.True(priceCount4 == 2, string.Format("Returns {0} facets of priceCount4 prices instead of 2", priceCount4));

            var sizeCount = GetFacetCount(results, "size", "0_to_5");

            Assert.True(sizeCount == 3, string.Format("Returns {0} facets of 0_to_5 size instead of 3", 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

            int outlineCount  = 0;
            var outlineObject = results.Documents.ElementAt(0)["__outline"]; // can be JArray or object[] depending on provider used

            if (outlineObject is JArray)
            {
                outlineCount = (outlineObject as JArray).Count;
            }
            else
            {
                outlineCount = (outlineObject as object[]).Count();
            }

            Assert.True(outlineCount == 2, string.Format("Returns {0} outlines instead of 2", outlineCount));
        }