private Query LoadFromState(AlgoliaQueryMapperState mappingState)
        {
            var query = new Query();

            var takeMethod = mappingState.AdditionalQueryMethods.OfType <TakeMethod>().FirstOrDefault();
            var skipMethod = mappingState.AdditionalQueryMethods.OfType <SkipMethod>().FirstOrDefault();

            if (takeMethod != null)
            {
                int take = takeMethod.Count;
                query.SetNbHitsPerPage(take);
                if (skipMethod != null)
                {
                    var skip = skipMethod.Count;

                    if (skip % take > 0)
                    {
                        throw new Exception("Skip and Take cannot be translated to number of pages");
                    }

                    var page = skip / take;
                    query.SetPage(page);
                }
            }
            else
            {
                if (skipMethod != null)
                {
                    throw new Exception("Skip cannot be used without Take.");
                }
            }

            //foreach (var method in mappingState.AdditionalQueryMethods)
            //{
            //    var takeMethod = method as TakeMethod;
            //    if (takeMethod != null)
            //    {
            //        query.SetNbHitsPerPage(takeMethod.Count);
            //        continue;
            //    }
            //    var skipMethod = method as SkipMethod;
            //    if (skipMethod != null)
            //    {
            //        query.SetPage(skipMethod.Count);
            //        continue;
            //    }
            //}
            return(query);
        }
		public async Task<int> CountStores(string query, IStoreFilter filter = null)
		{
			var algoliaQuery = new Algolia.Search.Query(query);
			algoliaQuery = getFilteredStoreQuery(algoliaQuery, filter);
			algoliaQuery.SetNbHitsPerPage(0);
			var result = await _storeIndex.SearchAsync(algoliaQuery);
			try
			{
				var count = result["nbHits"].ToObject<int>();
				return count;
			}
			catch
			{
			}
			return -1;
		}
		public async Task<IEnumerable<IStore>> FindStores(string query, int pageSize, int offset, IStoreFilter filter = null)
		{
			using (var tokenSource = new CancellationTokenSource(Constants.FindStoresTimeout))
			{
				var algoliaQuery = new Algolia.Search.Query(query);
				algoliaQuery = getFilteredStoreQuery(algoliaQuery, filter);
				if (pageSize > 0)
				{
					algoliaQuery.SetNbHitsPerPage(pageSize);
				}
				if (offset > 0)
				{
					algoliaQuery.SetPage(offset / pageSize);
				}
				var result = await _storeIndex.SearchAsync(algoliaQuery, tokenSource.Token);
				var stores = result["hits"].ToObject<List<Store>>();
				return stores;
			}
		}
		public async Task<IEnumerable<IProduct>> FindProducts(string query, int pageSize, int offset, IProductFilter filter = null)
		{
			using (var tokenSource = new CancellationTokenSource(Constants.FindProductsTimeout))
			{				
				var algoliaQuery = new Algolia.Search.Query(query);
				algoliaQuery = getFilteredProductQuery(algoliaQuery, filter);
				if (pageSize > 0)
				{
					algoliaQuery.SetNbHitsPerPage(pageSize);
				}
				if (offset > 0)
				{
					algoliaQuery.SetPage(offset / pageSize);
				}

				var result = await _productIndex.SearchAsync(algoliaQuery, tokenSource.Token);
				var products = result["hits"].ToObject<List<Product>>();
				await GetProductCategoryFacets(query, filter);
				return products;
			}
		}
		private async Task<Dictionary<string, int>> getProductAttributeFacets(string query, string facetAttribute, IProductFilter filter = null, params string[] childFacets)
		{
			var algoliaQuery = new Algolia.Search.Query(query);
			algoliaQuery = getFilteredProductQuery(algoliaQuery, filter, new string[] {facetAttribute}.Concatenate(childFacets));
			algoliaQuery.SetNbHitsPerPage(0);
			algoliaQuery.SetFacets(new string[] {facetAttribute});
			var result = await _productIndex.SearchAsync(algoliaQuery);
			try
			{
				var facets = result["facets"][facetAttribute].ToObject<Dictionary<string, int>>();
				return facets;
			}
			catch
			{
			}
			return null;
		}