internal IQueryResponse <Dictionary <string, object> > Execute(ElasticSearchQuery query, Type resultType) { var index = _context.Index as ElasticSearchIndex; if (index == null) { return(new QueryResponse <Dictionary <string, object> >()); } var descriptor = new SearchDescriptor <Dictionary <string, object> >(); descriptor.Query(query.Query); //TODO: need to determine how to allow type specification, so that we don't have to hard-code AllTypes //NEST generates the search query URL based on the descriptor type, so if we use Dictionary<string, object> as the descriptor type, the query URL is: //http://[server]:9200/[indexname]/dictionary`2s/_search //instead we want it to be: //http://[server]:9200/[indexname]/_search //when searching over all types. so basically, we want the default to AllTypes unless a specific type is used. //In the context of Sitecore search, is it even possible to specify a type for the search? probably, but would need some sort of type mapping... descriptor.AllTypes(); if (query.Filter != null) { descriptor.Filter(filterDescriptor => filterDescriptor.Query(q => query.Filter)); } if (!Settings.DefaultLanguage.StartsWith(_cultureCode)) { descriptor.Filter(f => f.Query(q => q.Term("_language", _cultureCode))); } var isResultsSizeSet = false; if (query.Methods != null) { var fields = new List <string>(); var selectMethods = (from m in query.Methods where m.MethodType == QueryMethodType.Select select(SelectMethod) m).ToList <SelectMethod>(); if (selectMethods.Any()) { foreach (var method in selectMethods) { fields.AddRange(method.FieldNames.Select(fieldName => fieldName.ToLowerInvariant())); } if (!_context.SecurityOptions.HasFlag(SearchSecurityOptions.DisableSecurityCheck)) { fields.Add("_uniqueid"); fields.Add("_datasource"); } } var getResultsMethods = (from m in query.Methods where m.MethodType == QueryMethodType.GetResults select(GetResultsMethod) m).ToList <GetResultsMethod>(); if (getResultsMethods.Any()) { if (fields.Count > 0) { fields.Add("score"); } } if (fields.Count > 0) { descriptor.Fields(fields.ToArray()); } var orderByMethods = (from m in query.Methods where m.MethodType == QueryMethodType.OrderBy select(OrderByMethod) m).ToList <OrderByMethod>(); if (orderByMethods.Any()) { foreach (var method in orderByMethods) { var fieldName = method.Field; switch (method.SortDirection) { case SortDirection.Ascending: descriptor.SortAscending(fieldName); break; case SortDirection.Descending: descriptor.SortDescending(fieldName); break; } } } var skipMethods = (from m in query.Methods where m.MethodType == QueryMethodType.Skip select(SkipMethod) m).ToList <SkipMethod>(); if (skipMethods.Any()) { var num = skipMethods.Sum(skipMethod => skipMethod.Count); descriptor.Skip(num); } var takeMethods = (from m in query.Methods where m.MethodType == QueryMethodType.Take select(TakeMethod) m).ToList <TakeMethod>(); if (takeMethods.Any()) { var num2 = takeMethods.Sum(takeMethod => takeMethod.Count); descriptor.Size(num2); //Take is actually just an alias for Size in NEST, so just use Size instead. isResultsSizeSet = true; } var countMethods = (from m in query.Methods where m.MethodType == QueryMethodType.Count select(CountMethod) m).ToList <CountMethod>(); if (query.Methods.Count == 1 && countMethods.Any()) { descriptor.Size(0); //TODO: is using Size appropriate here? and is "0" the proper value to send? isResultsSizeSet = true; } var anyMethods = (from m in query.Methods where m.MethodType == QueryMethodType.Any select(AnyMethod) m).ToList <AnyMethod>(); if (query.Methods.Count == 1 && anyMethods.Any()) { descriptor.Size(0); //TODO: is using Size appropriate here? and is "0" the proper value to send? isResultsSizeSet = true; } var getFacetsMethods = (from m in query.Methods where m.MethodType == QueryMethodType.GetFacets select(GetFacetsMethod) m).ToList <GetFacetsMethod>(); //TODO: implement facet querying if ((query.FacetQueries.Count > 0) && (getFacetsMethods.Any() || getResultsMethods.Any())) { //foreach (var facetQuery in GetFacetsPipeline.Run(new GetFacetsArgs(null, query.FacetQueries, _context.Index.Configuration.VirtualFieldProcessors, _context.Index.FieldNameTranslator)).FacetQueries.ToHashSet()) //{ // if (!facetQuery.FieldNames.Any()) // continue; // var nullable = facetQuery.MinimumResultCount; // if (facetQuery.FieldNames.Count() == 1) // { // var fieldNameTranslator = FieldNameTranslator as ElasticSearchFieldNameTranslator; // var indexFieldName = facetQuery.FieldNames.First(); // if (((fieldNameTranslator != null) && (indexFieldName == fieldNameTranslator.StripKnownExtensions(indexFieldName))) && (_context.Index.Configuration.FieldMap.GetFieldConfiguration(indexFieldName) == null)) // { // indexFieldName = fieldNameTranslator.GetIndexFieldName(indexFieldName.Replace("__", "!").Replace("_", " ").Replace("!", "__"), true); // } // IElasticSearchFacetQuery[] queries = new IElasticSearchFacetQuery[1]; // ElasticSearchFacetFieldQuery query2 = new ElasticSearchFacetFieldQuery(indexFieldName) // { // MinCount = nullable // }; // queries[0] = query2; // options.AddFacets(queries); // } // if (facetQuery.FieldNames.Any()) // { // IElasticSearchFacetQuery[] queryArray2 = new IElasticSearchFacetQuery[1]; // ElasticSearchFacetPivotQuery query3 = new ElasticSearchFacetPivotQuery // { // Fields = new[] { string.Join(",", facetQuery.FieldNames) }, // MinCount = nullable // }; // queryArray2[0] = query3; // options.AddFacets(queryArray2); // } //} } } if (!isResultsSizeSet) { descriptor.Size(ContentSearchConfigurationSettings.SearchMaxResults); } //var blee = JsonConvert.SerializeObject(descriptor, Formatting.Indented); var serializedDescriptor = index.Client.Serialize(descriptor); SearchLog.Log.Info("Serialized Query - " + serializedDescriptor); var response = index.Client.Search(descriptor); if (!response.ConnectionStatus.Success) { SearchLog.Log.Error("Query exception - " + response.ConnectionStatus.Error.OriginalException); } return(response); }