/// <summary>
        /// Gets a list of query suggestions for providing typeahead support.
        /// </summary>
        public override async Task <GetQuerySuggestionsResponse> GetQuerySuggestions(GetQuerySuggestionsRequest request, ServerCallContext context)
        {
            string            firstLetter       = request.Query.Substring(0, 1);
            PreparedStatement preparedStatement = await _statementCache.GetOrAddAsync("SELECT tag FROM tags_by_letter WHERE first_letter = ? AND tag >= ? LIMIT ?");

            BoundStatement boundStatement = preparedStatement.Bind(firstLetter, request.Query, request.PageSize);
            RowSet         rows           = await _session.ExecuteAsync(boundStatement).ConfigureAwait(false);

            var response = new GetQuerySuggestionsResponse
            {
                Query = request.Query
            };

            response.Suggestions.Add(rows.Select(row => row.GetValue <string>("tag")));
            return(response);
        }
Example #2
0
        /// <summary>
        /// Gets a list of query suggestions for providing typeahead support.
        /// </summary>
        public override async Task <GetQuerySuggestionsResponse> GetQuerySuggestions(GetQuerySuggestionsRequest request, ServerCallContext context)
        {
            // Get REST client for dse-search service
            Uri searchUri = await GetDseSearchUri().ConfigureAwait(false);

            IRestClient restClient = _createRestClient(searchUri);

            var restRequest = new RestRequest("killrvideo.videos/suggest")
            {
                Method = Method.POST
            };

            restRequest.AddParameter("wt", "json");

            // We'll build on every query, but in a real production app, we'd probably only do this occasionally or use the Solr config to setup
            // build on commit/optimize of the index
            restRequest.AddParameter("suggest.build", "true");
            restRequest.AddParameter("suggest.q", request.Query);
            IRestResponse <SearchResult> restResponse = await restClient.ExecuteTaskAsync <SearchResult>(restRequest).ConfigureAwait(false);

            // Start with an empty response (i.e. no suggestions)
            var response = new GetQuerySuggestionsResponse {
                Query = request.Query
            };

            // Check for network/timeout errors
            if (restResponse.ResponseStatus != ResponseStatus.Completed)
            {
                // TODO: Logger.Error(response.ErrorException, "Error while querying Solr search suggestions from {host} for {query}", nodeIp, getSuggestions.Query);
                return(response);
            }

            // Check for HTTP error codes
            if (restResponse.StatusCode != HttpStatusCode.OK)
            {
                // TODO: Logger.Error("HTTP status code {code} while querying Solr video suggestions from {host} for {query}", (int)response.StatusCode, nodeIp, getSuggestions.Query);
                return(response);
            }

            // Success, add responses from DSE Search to gRPC response
            response.Suggestions.Add(
                restResponse.Data.Suggest.SearchSuggester[request.Query].Suggestions.Select(s => s.Term)
                );

            return(response);
        }
        /// <summary>
        /// Gets a list of query suggestions for providing typeahead support.
        /// </summary>
        public override async Task <GetQuerySuggestionsResponse> GetQuerySuggestions(GetQuerySuggestionsRequest request, ServerCallContext context)
        {
            // Set the base URL of the REST client to use the first node in the Cassandra cluster
            string nodeIp = _session.Cluster.AllHosts().First().Address.Address.ToString();

            _restClient.BaseUrl = new Uri($"http://{nodeIp}:8983/solr");

            var restRequest = new RestRequest("killrvideo.videos/suggest")
            {
                Method = Method.POST
            };

            restRequest.AddParameter("wt", "json");

            // Requires a build after new names are added, added on a safe side.
            restRequest.AddParameter("spellcheck.build", "true");
            restRequest.AddParameter("spellcheck.q", request.Query);
            IRestResponse <SearchSuggestionResult> restResponse = await _restClient.ExecuteTaskAsync <SearchSuggestionResult>(restRequest).ConfigureAwait(false);

            // Start with an empty response (i.e. no suggestions)
            var response = new GetQuerySuggestionsResponse {
                Query = request.Query
            };

            // Check for network/timeout errors
            if (restResponse.ResponseStatus != ResponseStatus.Completed)
            {
                // TODO: Logger.Error(response.ErrorException, "Error while querying Solr search suggestions from {host} for {query}", nodeIp, getSuggestions.Query);
                return(response);
            }

            // Check for HTTP error codes
            if (restResponse.StatusCode != HttpStatusCode.OK)
            {
                // TODO: Logger.Error("HTTP status code {code} while querying Solr video suggestions from {host} for {query}", (int)response.StatusCode, nodeIp, getSuggestions.Query);
                return(response);
            }

            // Success

            /*
             * The spellcheck.suggestions object that comes back in the JSON looks something like this (for example, searching for 'cat'):
             *
             *  "suggestions": [
             *    "cat",
             *    {
             *      "numFound": 1,
             *      "startOffset": 0,
             *      "endOffset": 3,
             *      "suggestion": [
             *        "cat summer video teaser"
             *      ]
             *    }
             *  ]
             *
             * Yes, that's an array of mixed objects (seriously, WTF kind of an API is that Solr?!). Since the array is mixed, we deserialized
             * it as a List<string> where the second element will be the JSON string with the actual data we care about. We need to now run
             * deserialization again on that to get at the actual data.
             */
            if (restResponse.Data.Spellcheck.Suggestions.Count >= 2)
            {
                // Deserialize the embedded object
                var suggestions = JsonConvert.DeserializeObject <SearchSpellcheckSuggestions>(restResponse.Data.Spellcheck.Suggestions.Last());

                // Add to response if the object deserialized correctly
                if (suggestions.Suggestion != null)
                {
                    response.Suggestions.Add(suggestions.Suggestion);
                }
            }

            return(response);
        }