/// <summary> /// Translate a given request into QueryData. /// </summary> /// <param name="header">A header.</param> /// <param name="query">A query.</param> /// <returns>A <see cref="QueryData"/>.</returns> /// <exception cref="TranslateException">Throws a TranslateException on error.</exception> public QueryData TranslateQuery(string header, string query) { Ensure.IsNotNullOrEmpty(header, nameof(header)); try { Logger.LogDebug("Translate params: header:{@header}, query:{@query}", header, query.ToSensitiveData()); // Prepare the esDSL object, except some fields such as the query field which will be built later var elasticSearchDsl = JsonConvert.DeserializeObject <ElasticSearchDSL>(query); // deserialize the headers and extract the index name var headerDictionary = JsonConvert.DeserializeObject <Dictionary <string, string> >(header); Ensure.IsNotNull(elasticSearchDsl.Query, nameof(elasticSearchDsl.Query)); elasticSearchDsl.IndexName = headerDictionary["index"]; elasticSearchDsl.HighlightText = new Dictionary <string, string>(); List <string> sortFields = null; List <string> docValueFields = null; if (elasticSearchDsl.Query.Bool != null) { Ensure.IsNotNull(elasticSearchDsl.Query.Bool.Must, nameof(elasticSearchDsl.Query.Bool.Must)); if (elasticSearchDsl.Query.Bool.Filter.Any()) { // KQL in an experimental search syntax in Kibana that is turned on in version 7 but also available in version 6. // One can set it with option "search:queryLanguage" to "Lucene". More info: https://www.elastic.co/guide/en/kibana/current/advanced-options.html. Logger.LogWarning("Query includes a filter element indicating Kibana is working in KQL syntax, which is not supported yet. You should search with Lucene syntax instead."); } foreach (var element in elasticSearchDsl.Query.Bool.Must) { switch (element) { case QueryStringClause queryStringClause: elasticSearchDsl.HighlightText.Add("*", queryStringClause.Phrase); break; case MatchPhraseClause matchPhraseClause: elasticSearchDsl.HighlightText.Add(matchPhraseClause.FieldName, matchPhraseClause.Phrase); break; } } sortFields = new List <string>(); elasticSearchDsl.Sort?.ForEach(clause => sortFields.Add(clause.FieldName)); } else if (elasticSearchDsl.Query.Ids != null) { EnsureClause.IsNotNull(elasticSearchDsl.Query.Ids.Id, nameof(elasticSearchDsl.Query.Ids.Id)); Ensure.ConditionIsMet(elasticSearchDsl.Query.Ids.Id.Length == 1, $"{nameof(elasticSearchDsl.Query.Ids.Id)} must include exactly one value"); } else { throw new IllegalClauseException("Either Bool or Ids clauses must not be null"); } docValueFields = new List <string>(); elasticSearchDsl.DocValueFields?.ForEach(item => docValueFields.Add(item.Field)); // Use the visitor and build the KustoQL string from the esDSL object elasticSearchDsl.Accept(visitor); var queryData = new QueryData( elasticSearchDsl.KustoQL, elasticSearchDsl.IndexName, sortFields, docValueFields, elasticSearchDsl.HighlightText); if (elasticSearchDsl.Highlight != null) { Ensure.IsNotNullOrEmpty(elasticSearchDsl.Highlight.PreTags, nameof(elasticSearchDsl.Highlight.PreTags)); Ensure.IsNotNullOrEmpty(elasticSearchDsl.Highlight.PostTags, nameof(elasticSearchDsl.Highlight.PostTags)); queryData.HighlightPreTag = elasticSearchDsl.Highlight.PreTags[0]; queryData.HighlightPostTag = elasticSearchDsl.Highlight.PostTags[0]; } return(queryData); } catch (Exception ex) { Logger.LogError(ex, "Failed to execute translate operation."); throw new TranslateException("Failed translating elasticsearch query", ex); } }
/// <summary> /// Throws exception if luceneBoolObj is not a valid LuceneQuery. /// </summary> /// <param name="luceneBoolObj">luceneBoolObj to verify.</param> protected static void VerifyValid(ILuceneVisitable luceneBoolObj) { Ensure.IsNotNull(luceneBoolObj, nameof(luceneBoolObj)); EnsureClause.IsNotNull(luceneBoolObj.LuceneQuery, nameof(luceneBoolObj.LuceneQuery)); }