public override TResult Execute <TResult>(AzureQuery query)
        {
            if (EnumerableLinq.ShouldExecuteEnumerableLinqQuery(query))
            {
                return(EnumerableLinq.ExecuteEnumerableLinqQuery <TResult>(query));
            }
            if (!DoExecuteSearch(query))
            {
                return(ExecuteScalarMethod <TResult>(query));
            }
            if (typeof(TResult).IsGenericType && typeof(TResult).GetGenericTypeDefinition() == typeof(SearchResults <>))
            {
                var topDocs     = ExecuteQueryAgainstAzure(query);
                var type        = typeof(TResult).GetGenericArguments()[0];
                var methodInfo1 = GetType().GetMethod("ApplySearchMethods", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(type);
                var methodInfo2 = GetType().GetMethod("ApplyScalarMethods", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(typeof(TResult), type);
                var obj         = methodInfo1.Invoke(this, new object[2]
                {
                    query,
                    topDocs
                });
                return((TResult)methodInfo2.Invoke(this, new object[3]
                {
                    query,
                    obj,
                    topDocs
                }));
            }
            var topDocs1         = ExecuteQueryAgainstAzure(query);
            var processedResults = ApplySearchMethods <TResult>(query, topDocs1);

            return(ApplyScalarMethods <TResult, TResult>(query, processedResults, topDocs1));
        }
Exemple #2
0
        //private MapFieldSelector fieldSelector;

        public AzureSearchResults(AzureSearchContext context, AzureQuery query, DocumentSearchResult searchHits, int startIndex, int endIndex, SelectMethod selectMethod, IEnumerable <IExecutionContext> executionContexts, IEnumerable <IFieldQueryTranslator> virtualFieldProcessors, FieldNameTranslator fieldNameTranslator)
        {
            this.context                = context;
            this.query                  = query;
            this.searchHits             = searchHits;
            this.startIndex             = startIndex;
            this.endIndex               = endIndex;
            this.selectMethod           = selectMethod;
            this.virtualFieldProcessors = virtualFieldProcessors;
            this.fieldNameTranslator    = fieldNameTranslator;
            this.configuration          = (AzureIndexConfiguration)context.Index.Configuration;
            //this.fieldSelector = (MapFieldSelector)null;
            this.executionContexts = executionContexts;
            var executionContext = this.executionContexts != null?Enumerable.FirstOrDefault <IExecutionContext>(this.executionContexts, (Func <IExecutionContext, bool>)(c => c is OverrideExecutionContext <IIndexDocumentPropertyMapper <Document> >)) as OverrideExecutionContext <IIndexDocumentPropertyMapper <Document> > : (OverrideExecutionContext <IIndexDocumentPropertyMapper <Document> >)null;

            this.mapper = (executionContext != null ? executionContext.OverrideObject : null) ?? this.configuration.IndexDocumentPropertyMapper;
            //if (selectMethod != null && selectMethod.FieldNames != null && selectMethod.FieldNames.Length > 0)
            //{
            //    this.fieldSelector = this.GetMapFieldSelector(context, (IEnumerable<string>)selectMethod.FieldNames);
            //}
            //else
            //{
            //    if (this.selectMethod != null)
            //        return;
            //    IEnumerable<string> documentFieldsToRead = this.mapper.GetDocumentFieldsToRead<TElement>(executionContexts);
            //    this.fieldSelector = this.GetMapFieldSelector(context, documentFieldsToRead);
            //}
        }
        private Sitecore.ContentSearch.Linq.FacetResults ExecuteGetFacets(AzureQuery query)
        {
            var query1       = query;
            var list         = new List <FacetQuery>(query.FacetQueries);
            var facetQueries = GetFacetsPipeline.Run(pipeline, new GetFacetsArgs(null, query.FacetQueries, context.Index.Configuration.VirtualFields, context.Index.FieldNameTranslator)).FacetQueries;
            var facets       = new Dictionary <string, ICollection <KeyValuePair <string, int> > >();

            foreach (var facetQuery in facetQueries)
            {
                foreach (var keyValuePair in GetFacets(query1, facetQuery.FieldNames, new int?(1), Enumerable.Cast <string>(facetQuery.FilterValues), new bool?(), null, facetQuery.MinimumResultCount))
                {
                    facets[facetQuery.CategoryName] = keyValuePair.Value;
                }
            }
            var dictionary = ProcessFacetsPipeline.Run(pipeline, new ProcessFacetsArgs(facets, query.FacetQueries, list, context.Index.Configuration.VirtualFields, context.Index.FieldNameTranslator));

            foreach (var facetQuery in list)
            {
                var originalQuery = facetQuery;
                if (originalQuery.FilterValues != null && Enumerable.Any(originalQuery.FilterValues) && dictionary.ContainsKey(originalQuery.CategoryName))
                {
                    var collection = dictionary[originalQuery.CategoryName];
                    dictionary[originalQuery.CategoryName] = Enumerable.ToList(Enumerable.Where(collection, (cv => Enumerable.Contains(originalQuery.FilterValues, cv.Key))));
                }
            }
            var facetResults = new Sitecore.ContentSearch.Linq.FacetResults();

            foreach (var keyValuePair in dictionary)
            {
                IEnumerable <FacetValue> values = Enumerable.Select(keyValuePair.Value, v => new FacetValue(v.Key, v.Value));
                facetResults.Categories.Add(new FacetCategory(keyValuePair.Key, values));
            }
            return(facetResults);
        }
        private TResult ExecuteScalarMethod <TResult>(AzureQuery query)
        {
            var queryMethod = Enumerable.First(query.Methods);

            if (queryMethod.MethodType == QueryMethodType.GetFacets)
            {
                return((TResult)Convert.ChangeType(ExecuteGetFacets(query), typeof(TResult)));
            }

            var customMethod = queryMethod as CustomMethod;

            if (customMethod != null)
            {
                switch (customMethod.CustomMethodType)
                {
                case Linq.Nodes.CustomQueryMethodTypes.GetHightlights:
                    return((TResult)Convert.ChangeType(ExecuteGetHighlightResults(query), typeof(TResult)));

                default:
                    throw new InvalidOperationException("Invalid query method: " + customMethod.CustomMethodType);
                }
            }

            throw new InvalidOperationException("Invalid query method: " + queryMethod.MethodType);
        }
        public override IEnumerable <TElement> FindElements <TElement>(AzureQuery query)
        {
            if (EnumerableLinq.ShouldExecuteEnumerableLinqQuery(query))
            {
                return(EnumerableLinq.ExecuteEnumerableLinqQuery <IEnumerable <TElement> >(query));
            }
            var searchHits = ExecuteQueryAgainstAzure(query);

            return(ApplySearchMethods <TElement>(query, searchHits).GetSearchResults());
        }
        private int?GetTake(AzureQuery query)
        {
            var takeMethod = GetQueryMethod(query, QueryMethodType.Take);

            if (takeMethod != null)
            {
                return(((TakeMethod)takeMethod).Count);
            }

            return(null);
        }
        private SearchResults <TDocument> ExecuteGetResults <TDocument>(AzureQuery query, AzureSearchResults <TDocument> processedResults, DocumentSearchResult results)
        {
            var searchHits = processedResults.GetSearchHits();

            Sitecore.ContentSearch.Linq.FacetResults facets = null;
            if (query.FacetQueries != null && query.FacetQueries.Count > 0)
            {
                facets = ExecuteGetFacets(query);
            }
            return(new SearchResults <TDocument>(searchHits, (int)results.Count, facets));
        }
        private int?GetSkip(AzureQuery query)
        {
            var skipMethod = GetQueryMethod(query, QueryMethodType.Skip);

            if (skipMethod != null)
            {
                return(((SkipMethod)skipMethod).Count);
            }

            return(null);
        }
        private QueryMethod GetQueryMethod(AzureQuery query, QueryMethodType type)
        {
            foreach (var method in query.Methods)
            {
                if (method.MethodType == type)
                {
                    return(method);
                }
            }

            return(null);
        }
        private void GetPaging(AzureQuery query, int totalHits, out int startIdx, out int endIdx)
        {
            var list = query.Methods != null ? new List <QueryMethod>(query.Methods) : new List <QueryMethod>();

            list.Reverse();
            startIdx = 0;
            endIdx   = totalHits - 1;
            int num = endIdx;

            foreach (QueryMethod queryMethod in list)
            {
                switch (queryMethod.MethodType)
                {
                case QueryMethodType.Skip:
                    int count1 = ((SkipMethod)queryMethod).Count;
                    if (count1 > 0)
                    {
                        startIdx += count1;
                        continue;
                    }
                    continue;

                case QueryMethodType.Take:
                    int count2 = ((TakeMethod)queryMethod).Count;
                    if (count2 <= 0)
                    {
                        endIdx = startIdx++;
                        continue;
                    }
                    endIdx = startIdx + count2 - 1;
                    if (endIdx > num)
                    {
                        endIdx = num;
                        continue;
                    }
                    if (num < endIdx)
                    {
                        num = endIdx;
                        continue;
                    }
                    continue;

                default:
                    continue;
                }
            }
            if (!settings.EnableSearchDebug())
            {
                return;
            }
            SearchLog.Log.Debug(string.Format("Indexes: {0} - {1}", startIdx, endIdx), null);
        }
        public void AzureQueryShouldCreateWhereExp()
        {
            var result = AzureQuery.CreateQueryFilters("Prop1 eq 1 AND Prop2 ne 2").ToArray();

            Assert.AreEqual(result[0].FilterType, QueryFilterType.Where);
            Assert.AreEqual(result[0].Operator, QueryFilterOperator.Equal);
            Assert.AreEqual(result[0].Property, "Prop1");
            Assert.AreEqual(result[0].Value, "1");
            Assert.AreEqual(result[1].FilterType, QueryFilterType.And);
            Assert.AreEqual(result[1].Operator, QueryFilterOperator.NotEqual);
            Assert.AreEqual(result[1].Property, "Prop2");
            Assert.AreEqual(result[1].Value, "2");
        }
        private AzureSearchResults <TElement> ApplySearchMethods <TElement>(AzureQuery query, DocumentSearchResult searchHits)
        {
            var list = query.Methods != null ? new List <QueryMethod>(query.Methods) : new List <QueryMethod>();

            list.Reverse();
            SelectMethod selectMethod = null;

            foreach (var queryMethod in list)
            {
                if (queryMethod.MethodType == QueryMethodType.Select)
                {
                    selectMethod = (SelectMethod)queryMethod;
                }
            }
            int startIndex = 0;
            int endIndex   = searchHits.Results.Count - 1;

            return(new AzureSearchResults <TElement>(context, query, searchHits, startIndex, endIndex, selectMethod, query.ExecutionContexts, query.VirtualFieldProcessors, FieldNameTranslator));
        }
        private bool DoExecuteSearch(AzureQuery query)
        {
            var retVal = true;

            if (Enumerable.First(query.Methods).MethodType == QueryMethodType.GetFacets)
            {
                retVal = false;
            }

            if (query.Methods.FirstOrDefault().MethodType == QueryMethodType.All)
            {
                var customMethod = query.Methods.FirstOrDefault() as CustomMethod;
                if (customMethod != null)
                {
                    retVal = false;
                }
            }

            return(retVal);
        }
        public void AzureQueryShouldCreateOrExp()
        {
            var result = AzureQuery.CreateQueryFilters("A < 1 OR B > 2 OR C <= 3 OR D >= 4").ToArray();

            Assert.AreEqual(result[0].FilterType, QueryFilterType.Where);
            Assert.AreEqual(result[0].Operator, QueryFilterOperator.Lower);
            Assert.AreEqual(result[0].Property, "A");
            Assert.AreEqual(result[0].Value, "1");
            Assert.AreEqual(result[1].FilterType, QueryFilterType.Or);
            Assert.AreEqual(result[1].Operator, QueryFilterOperator.Greater);
            Assert.AreEqual(result[1].Property, "B");
            Assert.AreEqual(result[1].Value, "2");
            Assert.AreEqual(result[2].FilterType, QueryFilterType.Or);
            Assert.AreEqual(result[2].Operator, QueryFilterOperator.LowerEqual);
            Assert.AreEqual(result[2].Property, "C");
            Assert.AreEqual(result[2].Value, "3");
            Assert.AreEqual(result[3].FilterType, QueryFilterType.Or);
            Assert.AreEqual(result[3].Operator, QueryFilterOperator.GreaterEqual);
            Assert.AreEqual(result[3].Property, "D");
            Assert.AreEqual(result[3].Value, "4");
        }
        protected virtual Sort GetSorting(AzureQuery query)
        {
            Assert.ArgumentNotNull(query, "query");
            Sort sort = null;

            if (query.Methods != null)
            {
                var sortFieldArray = Enumerable.ToArray(Enumerable.Reverse(Enumerable.Select(Enumerable.Where(query.Methods, m => m.MethodType == QueryMethodType.OrderBy), (m => new SortField(((OrderByMethod)m).Field, GetSortFieldType((OrderByMethod)m), ((OrderByMethod)m).SortDirection == SortDirection.Descending)))));
                if (sortFieldArray.Length > 0)
                {
                    sort = new Sort(sortFieldArray);
                    if (settings.EnableSearchDebug())
                    {
                        var stringBuilder = new StringBuilder();
                        foreach (var sortField in sortFieldArray)
                        {
                            stringBuilder.Append(sortField.Field.Replace("sortfield", string.Empty) + " ");
                        }
                        SearchLog.Log.Debug(string.Format("Sorting Azure query by{0}", stringBuilder), null);
                    }
                }
            }
            return(sort);
        }
        private IDictionary <string, ICollection <KeyValuePair <string, int> > > GetFacets(AzureQuery query, IEnumerable <string> facetFields, int?minResultCount, IEnumerable <string> filters, bool?sort, string prefix, int?limit)
        {
            Assert.ArgumentNotNull(query, "query");
            Assert.ArgumentNotNull(facetFields, "facetFields");

            SearchLog.Log.Info(string.Format("GetFacets : {0} : {1}{2}", string.Join(",", facetFields), query, filters != null ? (" Filters: " + string.Join(",", filters)) : string.Empty), null);
            var dictionary   = new Dictionary <string, ICollection <KeyValuePair <string, int> > >();
            var searchResult = ExecuteQueryAgainstAzure(query, facetFields);

            var minCount = limit.HasValue ? limit.Value : 0;

            foreach (var facetResult in searchResult.Facets)
            {
                var vals = facetResult.Value.Where(s => s.Count.Value >= minCount).Select(s => new KeyValuePair <string, int>(s.Value.ToString(), (int)s.Count.Value)).ToList();
                dictionary.Add(facetResult.Key, vals);
            }

            return(dictionary);
        }
        private TResult ApplyScalarMethods <TResult, TDocument>(AzureQuery query, AzureSearchResults <TDocument> processedResults, DocumentSearchResult results)
        {
            var    queryMethod = query.Methods.FirstOrDefault();
            object obj;

            switch (queryMethod.MethodType)
            {
            case QueryMethodType.All:
                obj = true;
                //Check for CustomMethod
                var customMethod = queryMethod as CustomMethod;
                if (customMethod != null)
                {
                    switch (customMethod.CustomMethodType)
                    {
                    case Linq.Nodes.CustomQueryMethodTypes.GetHightlights:
                        obj = ExecuteGetHighlightResults(query);
                        break;
                    }
                }
                break;

            case QueryMethodType.Any:
                obj = (processedResults.Any() ? 1 : 0);
                break;

            case QueryMethodType.Count:
                obj = query.Methods.Any(m =>
                {
                    if (m.MethodType != QueryMethodType.Skip)
                    {
                        return(m.MethodType == QueryMethodType.Take);
                    }
                    return(true);
                }) ? processedResults.Count() : results.Count;
                break;

            case QueryMethodType.ElementAt:
                obj = !((ElementAtMethod)queryMethod).AllowDefaultValue ? processedResults.ElementAt(((ElementAtMethod)queryMethod).Index) : processedResults.ElementAtOrDefault(((ElementAtMethod)queryMethod).Index);
                break;

            case QueryMethodType.First:
                obj = !((FirstMethod)queryMethod).AllowDefaultValue ? processedResults.First() : processedResults.FirstOrDefault();
                break;

            case QueryMethodType.Last:
                obj = !((LastMethod)queryMethod).AllowDefaultValue ? processedResults.Last() : processedResults.LastOrDefault();
                break;

            case QueryMethodType.Single:
                obj = !((SingleMethod)queryMethod).AllowDefaultValue ? processedResults.Single() : processedResults.SingleOrDefault();
                break;

            case QueryMethodType.GetResults:
                obj = ExecuteGetResults <TDocument>(query, processedResults, results);
                break;

            case QueryMethodType.GetFacets:
                obj = ExecuteGetFacets(query);
                break;

            default:
                throw new InvalidOperationException("Invalid query method: " + queryMethod.MethodType);
            }
            return((TResult)Convert.ChangeType(obj, typeof(TResult)));
        }
        private DocumentSearchResult ExecuteQueryAgainstAzure(AzureQuery query, IEnumerable <string> facetFields = null, IEnumerable <string> highlightFields = null)
        {
            if (settings.EnableSearchDebug())
            {
                var stringBuilder = new StringBuilder();
                stringBuilder.AppendLine("Executing azure query: " + query);
                foreach (var queryMethod in query.Methods)
                {
                    stringBuilder.AppendLine("    - " + queryMethod);
                }
                stringBuilder.AppendLine();
                stringBuilder.AppendLine(AzureQueryLogger.Trace(query.Query));
                stringBuilder.AppendLine("Rewritten Lucene Query:");
                stringBuilder.AppendLine();
                //stringBuilder.AppendLine(AzureQueryLogger.Trace(query.Query.Rewrite(Enumerable.First<IAzureProviderSearchable>(context.Searchables).CreateSearcher(AzureIndexAccess.ReadOnlyCached).IndexReader)));
                SearchLog.Log.Debug(stringBuilder.ToString(), null);
            }

            var  getResultsMethod = Enumerable.FirstOrDefault(query.Methods, m => m.MethodType == QueryMethodType.GetResults) as GetResultsMethod;
            bool trackDocScores   = getResultsMethod != null && (getResultsMethod.Options & GetResultsOptions.GetScores) == GetResultsOptions.GetScores;

            var indexClient  = ((AzureIndex)context.Index).AzureSearchClient;
            var searchParams = new SearchParameters();

            searchParams.IncludeTotalResultCount = true;
            searchParams.SearchMode = SearchMode.Any;
            searchParams.QueryType  = QueryType.Full;

            var sorting = GetSorting(query);

            if (sorting != null)
            {
                searchParams.OrderBy = new List <string>();
                foreach (var sort in sorting.GetSort())
                {
                    searchParams.OrderBy.Add(sort.Field + (sort.Reverse ? " desc" : " asc"));
                }
            }

            if (query.Filter != null)
            {
                searchParams.Filter = query.Filter.ToString();
            }

            if (facetFields != null && facetFields.Any())
            {
                searchParams.Facets = new List <string>();
                foreach (var facetField in facetFields)
                {
                    searchParams.Facets.Add(facetField);
                }
            }

            if (highlightFields != null && highlightFields.Any())
            {
                searchParams.HighlightPreTag  = query.HighlightPreTag;
                searchParams.HighlightPostTag = query.HighlightPostTag;
                searchParams.HighlightFields  = new List <string>();
                foreach (var highlightField in highlightFields)
                {
                    searchParams.HighlightFields.Add(highlightField);
                }
            }

            //var weight = context.Searcher.CreateWeight(query.Query);

            var skip = GetSkip(query);

            if (skip.HasValue)
            {
                searchParams.Skip = skip.Value;
            }
            var take = GetTake(query);

            if (take.HasValue)
            {
                searchParams.Top = take.Value;
            }
            else
            {
                searchParams.Top = 1000; //Max Azure Search allows per request.
            }

            //TODO:  Figure out how to fix the '+=' issue in AzureQueryMapper
            var strQuery = query.ToString().Replace("+-", "-");

            SearchLog.Log.Info(string.Format("ExecuteQueryAgainstAzure ({0}): {1} - Filter : {2} - Facets : {3} - Highlights : {4}", context.Index.Name, strQuery, query.Filter != null ? query.Filter.ToString() : string.Empty, query.FacetQueries != null ? string.Join(", ", query.FacetQueries) : string.Empty, query.Highlights != null ? string.Join(", ", query.Highlights) : string.Empty), null);

            var responseTask = indexClient.Documents.SearchWithHttpMessagesAsync(strQuery, searchParams);

            responseTask.Wait();
            var response = responseTask.Result.Body;

            if (settings.EnableSearchDebug())
            {
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.AppendFormat("fieldSortDoTrackScores: {0}\n", (trackDocScores ? 1 : 0));
                stringBuilder.AppendFormat("Collector TotalHits:    {0}\n", response.Count);
                stringBuilder.AppendFormat("Docs TotalHits:      {0}\n", response.Count);
                SearchLog.Log.Debug(stringBuilder.ToString());
            }

            return(response);
        }
        private HighlightSearchResults <AzureSearchResultItem> ExecuteGetHighlightResults(AzureQuery query)
        {
            var results = ExecuteQueryAgainstAzure(query, null, query.Highlights);
            var hits    = ApplySearchMethods <AzureSearchResultItem>(query, results).GetSearchHits().ToList();

            if (query.MergeHighlights)
            {
                for (var i = 0; i < hits.Count; i++)
                {
                    foreach (var highlight in hits[i].HighlightResults)
                    {
                        hits[i].Document.SetValueByIndexFieldName(highlight.Name, highlight.Values.FirstOrDefault());
                    }
                }
            }

            var azureResults = new HighlightSearchResults <AzureSearchResultItem>(hits, (int)results.Count);

            return(azureResults);
        }
        private int GetMaxHits(AzureQuery query, int maxDoc)
        {
            var list = query.Methods != null ? new List <QueryMethod>(query.Methods) : new List <QueryMethod>();

            list.Reverse();
            var modifierScalarMethod = GetMaxHitsModifierScalarMethod(query.Methods);
            int num1 = 0;
            int num2 = maxDoc - 1;
            int num3 = num2;
            int num4 = num2;

            foreach (var queryMethod in list)
            {
                switch (queryMethod.MethodType)
                {
                case QueryMethodType.Skip:
                    int count = ((SkipMethod)queryMethod).Count;
                    if (count > 0)
                    {
                        num1 += count;
                        continue;
                    }
                    continue;

                case QueryMethodType.Take:
                    int num5 = ((TakeMethod)queryMethod).Count;
                    if (num5 <= 0)
                    {
                        num2 = num1++;
                        continue;
                    }
                    if (num5 > 1 && modifierScalarMethod != null && modifierScalarMethod.MethodType == QueryMethodType.First)
                    {
                        num5 = 1;
                    }
                    if (num5 > 1 && modifierScalarMethod != null && modifierScalarMethod.MethodType == QueryMethodType.Any)
                    {
                        num5 = 1;
                    }
                    if (num5 > 2 && modifierScalarMethod != null && modifierScalarMethod.MethodType == QueryMethodType.Single)
                    {
                        num5 = 2;
                    }
                    num2 = num1 + num5 - 1;
                    if (num2 > num3)
                    {
                        num2 = num3;
                        continue;
                    }
                    if (num3 < num2)
                    {
                        num3 = num2;
                        continue;
                    }
                    continue;

                default:
                    continue;
                }
            }
            if (num4 == num2)
            {
                int num5 = -1;
                if (modifierScalarMethod != null && modifierScalarMethod.MethodType == QueryMethodType.First)
                {
                    num5 = 1;
                }
                if (modifierScalarMethod != null && modifierScalarMethod.MethodType == QueryMethodType.Any)
                {
                    num5 = 1;
                }
                if (modifierScalarMethod != null && modifierScalarMethod.MethodType == QueryMethodType.Single)
                {
                    num5 = 2;
                }
                if (num5 >= 0)
                {
                    num2 = num1 + num5 - 1;
                    if (num2 > num3)
                    {
                        num2 = num3;
                    }
                    else if (num3 < num2)
                    {
                        ;
                    }
                }
            }
            if (num4 == num2 && num1 == 0 && (modifierScalarMethod != null && modifierScalarMethod.MethodType == QueryMethodType.Count))
            {
                num2 = -1;
            }
            int num6 = num2 + 1;

            if (settings.EnableSearchDebug())
            {
                SearchLog.Log.Debug(string.Format("Max hits: {0}", num6), null);
            }
            return(num6);
        }