private string[] QueryOverMultipleWords(SuggestionQueryServerSide parameters, string queryText) { parameters.Popularity = false; var individualTerms = queryText.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var result = new HashSet <string>(); var currentMaxSuggestions = parameters.MaxSuggestions; foreach (var term in individualTerms) { if (currentMaxSuggestions <= 0) { break; } foreach (var suggestion in QueryOverSingleWord(parameters, term)) { if (result.Add(suggestion) == false) { continue; } currentMaxSuggestions--; if (currentMaxSuggestions <= 0) { break; } } } return(result.ToArray()); }
private SuggestionQueryServerSide GetSuggestionQuery(JsonOperationContext context, HttpMethod method) { if (method == HttpMethod.Get) { throw new NotImplementedException("RavenDB-8882"); } var indexQueryJson = context.ReadForMemory(RequestBodyStream(), "suggestion/query"); // read from cache here return(SuggestionQueryServerSide.Create(indexQueryJson)); }
private SuggestionQueryServerSide GetSuggestionQuery(JsonOperationContext context, HttpMethod method) { if (method == HttpMethod.Get) { //MoreLikeThisQueryServerSide.Create(HttpContext, GetPageSize(), context); throw new NotImplementedException(); } var indexQueryJson = context.ReadForMemory(RequestBodyStream(), "suggestion/query"); // read from cache here return(SuggestionQueryServerSide.Create(indexQueryJson)); }
public string[] Suggestions(SuggestionQueryServerSide query, CancellationToken token) { var term = query.Term; if (term.StartsWith("<<") && term.EndsWith(">>")) { return(QueryOverMultipleWords(query, term.Substring(2, term.Length - 4))); } if (term.StartsWith("(") && term.EndsWith(")")) { return(QueryOverMultipleWords(query, term.Substring(1, term.Length - 2))); } return(QueryOverSingleWord(query, term)); }
private string[] QueryOverSingleWord(SuggestionQueryServerSide parameters, string word) { // Perform devirtualization of the distance function when supported. switch (parameters.Distance) { case StringDistanceTypes.JaroWinkler: return(QueryOverSingleWord(parameters, word, new JaroWinklerDistance())); case StringDistanceTypes.NGram: return(QueryOverSingleWord(parameters, word, new NGramDistance())); case StringDistanceTypes.Default: case StringDistanceTypes.Levenshtein: default: return(QueryOverSingleWord(parameters, word, new LevenshteinDistance())); } }
public SuggestionQueryResultServerSide ExecuteSuggestionQuery(SuggestionQueryServerSide query, DocumentsOperationContext context, long?existingResultEtag, OperationCancelToken token) { if (query == null) { throw new ArgumentNullException(nameof(query)); } // Check pre-requisites for the query to happen. if (string.IsNullOrWhiteSpace(query.Term)) { throw new InvalidOperationException("Suggestions queries require a term."); } if (string.IsNullOrWhiteSpace(query.Field)) { throw new InvalidOperationException("Suggestions queries require a field."); } var sw = Stopwatch.StartNew(); // Check definition for the index. var index = GetIndex(query.IndexName); var indexDefinition = index.GetIndexDefinition(); if (indexDefinition == null) { throw new InvalidOperationException($"Could not find specified index '{this}'."); } if (indexDefinition.Fields.TryGetValue(query.Field, out IndexFieldOptions field) == false) { throw new InvalidOperationException($"Index '{this}' does not have a field '{query.Field}'."); } if (field.Suggestions == null) { throw new InvalidOperationException($"Index '{this}' does not have suggestions configured for field '{query.Field}'."); } if (field.Suggestions.Value == false) { throw new InvalidOperationException($"Index '{this}' have suggestions explicitly disabled for field '{query.Field}'."); } if (existingResultEtag.HasValue) { var etag = index.GetIndexEtag(); if (etag == existingResultEtag.Value) { return(SuggestionQueryResultServerSide.NotModifiedResult); } } context.OpenReadTransaction(); var result = index.SuggestionsQuery(query, context, token); result.DurationInMs = (int)sw.Elapsed.TotalMilliseconds; return(result); }
private string[] QueryOverSingleWord <TDistance>(SuggestionQueryServerSide parameters, string word, TDistance sd) where TDistance : IStringDistance { float min = parameters.Accuracy.Value; string field = parameters.Field; int numSug = parameters.MaxSuggestions; bool morePopular = parameters.Popularity; int lengthWord = word.Length; var ir = _searcher.IndexReader; int freq = (ir != null && field != null) ? ir.DocFreq(new Term(FWord, word), _state) : 0; int goalFreq = (morePopular && ir != null && field != null) ? freq : 0; // if the word exists in the real index and we don't care for word frequency, return the word itself if (!morePopular && freq > 0) { return(new[] { word }); } var query = new BooleanQuery(); var alreadySeen = new HashSet <string>(); int ng = GetMin(lengthWord); int max = ng + 1; var table = GramsTable; for (; ng <= max; ng++) { string[] grams = FormGrams(word, ng); if (grams.Length == 0) { continue; // hmm } if (BoostStart > 0) { // should we boost prefixes? Add(query, table[ng].Start, grams[0], BoostStart); // matches start of word } if (BoostEnd > 0) { // should we boost suffixes Add(query, table[ng].End, grams[grams.Length - 1], BoostEnd); // matches end of word } for (int i = 0; i < grams.Length; i++) { Add(query, table[ng].Gram, grams[i]); } } int maxHits = 10 * numSug; // System.out.println("Q: " + query); ScoreDoc[] hits = _searcher.Search(query, null, maxHits, _state).ScoreDocs; // System.out.println("HITS: " + hits.length()); var queue = new SuggestWordQueue(numSug); // go thru more than 'maxr' matches in case the distance filter triggers int stop = Math.Min(hits.Length, maxHits); var suggestedWord = new SuggestWord(); for (int i = 0; i < stop; i++) { suggestedWord.Term = _searcher.Doc(hits[i].Doc, _state).Get(FWord, _state); // get orig word // don't suggest a word for itself, that would be silly if (suggestedWord.Term.Equals(word, StringComparison.OrdinalIgnoreCase)) { continue; } // edit distance suggestedWord.Score = sd.GetDistance(word, suggestedWord.Term); if (suggestedWord.Score < min) { continue; } if (ir != null && field != null) { // use the user index suggestedWord.Freq = _searcher.DocFreq(new Term(FWord, suggestedWord.Term), _state); // freq in the index // don't suggest a word that is not present in the field if ((morePopular && goalFreq > suggestedWord.Freq) || suggestedWord.Freq < 1) { continue; } } if (alreadySeen.Add(suggestedWord.Term) == false) // we already seen this word, no point returning it twice { continue; } queue.InsertWithOverflow(suggestedWord); if (queue.Size() == numSug) { // if queue full, maintain the minScore score min = queue.Top().Score; } suggestedWord = new SuggestWord(); } int size = queue.Size(); if (size == 0) { return(EmptyArray); } // convert to array string string[] list = new string[size]; for (int i = size - 1; i >= 0; i--) { list[i] = queue.Pop().Term; } return(list); }