private ExplanationResult GetQueryExplanations(ExplanationOptions options, Query luceneQuery, IndexSearcher searcher, ScoreDoc scoreDoc, Document document, global::Lucene.Net.Documents.Document luceneDocument) { string key; var hasGroupKey = options != null && string.IsNullOrWhiteSpace(options.GroupKey) == false; if (_indexType.IsMapReduce()) { if (hasGroupKey) { key = luceneDocument.Get(options.GroupKey, _state); if (key == null && document.Data.TryGet(options.GroupKey, out object value)) { key = value?.ToString(); } } else { key = luceneDocument.Get(Constants.Documents.Indexing.Fields.ReduceKeyHashFieldName, _state); } } else { key = hasGroupKey ? luceneDocument.Get(options.GroupKey, _state) : document.Id; } return(new ExplanationResult { Key = key, Explanation = searcher.Explain(luceneQuery, scoreDoc.Doc, _state) }); }
public void IncludeExplanations(ExplanationOptions options, out Explanations explanations) { if (ExplanationToken != null) { throw new InvalidOperationException($"Duplicate '{nameof(IncludeExplanations)}' method calls are forbidden."); } var optionsParameterName = options != null?AddQueryParameter(options) : null; ExplanationToken = ExplanationToken.Create(optionsParameterName); Explanations = explanations = new Explanations(); }
private ExplanationResult GetQueryExplanations(ExplanationOptions options, Query luceneQuery, IndexSearcher searcher, ScoreDoc scoreDoc, Document document, global::Lucene.Net.Documents.Document luceneDocument) { string key; if (options != null && string.IsNullOrWhiteSpace(options.GroupKey) == false) { key = luceneDocument.Get(options.GroupKey, _state); } else { key = document.Id; } return(new ExplanationResult { Key = key, Explanation = searcher.Explain(luceneQuery, scoreDoc.Doc, _state) }); }
public ExplanationOptions GetOptions(JsonOperationContext context, BlittableJsonReaderObject parameters) { if (_options != null) { return(_options); } if (_optionsAsStringOrParameterName == null) { return(null); } var options = FieldOptionsHelper.GetOptions <ExplanationOptions>(_optionsAsStringOrParameterName, _optionsType, parameters, context); if (_optionsType == ValueTokenType.String) { _options = options; } return(options); }
public IEnumerable <(Document Result, Dictionary <string, Dictionary <string, string[]> > Highlightings, ExplanationResult Explanation)> Query(IndexQueryServerSide query, QueryTimingsScope queryTimings, FieldsToFetch fieldsToFetch, Reference <int> totalResults, Reference <int> skippedResults, IQueryResultRetriever retriever, DocumentsOperationContext documentsContext, Func <string, SpatialField> getSpatialField, CancellationToken token) { ExplanationOptions explanationOptions = null; var pageSize = query.PageSize; var isDistinctCount = pageSize == 0 && query.Metadata.IsDistinct; if (isDistinctCount) { pageSize = int.MaxValue; } pageSize = GetPageSize(_searcher, pageSize); var docsToGet = pageSize; var position = query.Start; if (query.Metadata.IsOptimizedSortOnly && _index.Definition.HasDynamicFields == false) { foreach (var result in QuerySortOnly(query, retriever, position, pageSize, totalResults, token)) { yield return(result); } yield break; } QueryTimingsScope luceneScope = null; QueryTimingsScope highlightingScope = null; QueryTimingsScope explanationsScope = null; if (queryTimings != null) { luceneScope = queryTimings.For(nameof(QueryTimingsScope.Names.Lucene), start: false); highlightingScope = query.Metadata.HasHighlightings ? queryTimings.For(nameof(QueryTimingsScope.Names.Highlightings), start: false) : null; explanationsScope = query.Metadata.HasExplanations ? queryTimings.For(nameof(QueryTimingsScope.Names.Explanations), start: false) : null; } var returnedResults = 0; var luceneQuery = GetLuceneQuery(documentsContext, query.Metadata, query.QueryParameters, _analyzer, _queryBuilderFactories); var sort = GetSort(query, _index, getSpatialField, documentsContext); using (var scope = new IndexQueryingScope(_indexType, query, fieldsToFetch, _searcher, retriever, _state)) { if (query.Metadata.HasHighlightings) { using (highlightingScope?.For(nameof(QueryTimingsScope.Names.Setup))) SetupHighlighter(query, luceneQuery, documentsContext); } while (true) { token.ThrowIfCancellationRequested(); TopDocs search; using (luceneScope?.Start()) search = ExecuteQuery(luceneQuery, query.Start, docsToGet, sort); totalResults.Value = search.TotalHits; scope.RecordAlreadyPagedItemsInPreviousPage(search); for (; position < search.ScoreDocs.Length && pageSize > 0; position++) { token.ThrowIfCancellationRequested(); var scoreDoc = search.ScoreDocs[position]; global::Lucene.Net.Documents.Document document; using (luceneScope?.Start()) document = _searcher.Doc(scoreDoc.Doc, _state); if (retriever.TryGetKey(document, _state, out string key) && scope.WillProbablyIncludeInResults(key) == false) { skippedResults.Value++; continue; } var result = retriever.Get(document, scoreDoc.Score, _state); if (scope.TryIncludeInResults(result) == false) { skippedResults.Value++; continue; } returnedResults++; if (isDistinctCount == false) { Dictionary <string, Dictionary <string, string[]> > highlightings = null; if (query.Metadata.HasHighlightings) { using (highlightingScope?.Start()) highlightings = GetHighlighterResults(query, _searcher, scoreDoc, result, document, documentsContext); } ExplanationResult explanation = null; if (query.Metadata.HasExplanations) { using (explanationsScope?.Start()) { if (explanationOptions == null) { explanationOptions = query.Metadata.Explanation.GetOptions(documentsContext, query.QueryParameters); } explanation = GetQueryExplanations(explanationOptions, luceneQuery, _searcher, scoreDoc, result, document); } } yield return(result, highlightings, explanation); } if (returnedResults == pageSize) { yield break; } } if (search.TotalHits == search.ScoreDocs.Length) { break; } if (returnedResults >= pageSize) { break; } Debug.Assert(_maxNumberOfOutputsPerDocument > 0); docsToGet += GetPageSize(_searcher, (long)(pageSize - returnedResults) * _maxNumberOfOutputsPerDocument); } if (isDistinctCount) { totalResults.Value = returnedResults; } } }
public IEnumerable <QueryResult> Query(IndexQueryServerSide query, QueryTimingsScope queryTimings, FieldsToFetch fieldsToFetch, Reference <int> totalResults, Reference <int> skippedResults, Reference <int> scannedDocuments, IQueryResultRetriever retriever, DocumentsOperationContext documentsContext, Func <string, SpatialField> getSpatialField, CancellationToken token) { ExplanationOptions explanationOptions = null; var pageSize = query.PageSize; var isDistinctCount = pageSize == 0 && query.Metadata.IsDistinct; if (isDistinctCount) { pageSize = int.MaxValue; } pageSize = GetPageSize(_searcher, pageSize); var docsToGet = pageSize; var position = query.Start; QueryTimingsScope luceneScope = null; QueryTimingsScope highlightingScope = null; QueryTimingsScope explanationsScope = null; if (queryTimings != null) { luceneScope = queryTimings.For(nameof(QueryTimingsScope.Names.Lucene), start: false); highlightingScope = query.Metadata.HasHighlightings ? queryTimings.For(nameof(QueryTimingsScope.Names.Highlightings), start: false) : null; explanationsScope = query.Metadata.HasExplanations ? queryTimings.For(nameof(QueryTimingsScope.Names.Explanations), start: false) : null; } var returnedResults = 0; var luceneQuery = GetLuceneQuery(documentsContext, query.Metadata, query.QueryParameters, _analyzer, _queryBuilderFactories); using (var queryFilter = GetQueryFilter(_index, query, documentsContext, skippedResults, scannedDocuments, retriever, queryTimings)) using (GetSort(query, _index, getSpatialField, documentsContext, out var sort)) using (var scope = new IndexQueryingScope(_indexType, query, fieldsToFetch, _searcher, retriever, _state)) { if (query.Metadata.HasHighlightings) { using (highlightingScope?.For(nameof(QueryTimingsScope.Names.Setup))) SetupHighlighter(query, luceneQuery, documentsContext); } while (true) { token.ThrowIfCancellationRequested(); TopDocs search; using (luceneScope?.Start()) search = ExecuteQuery(luceneQuery, query.Start, docsToGet, sort); totalResults.Value = search.TotalHits; scope.RecordAlreadyPagedItemsInPreviousPage(search, token); for (; position < search.ScoreDocs.Length && pageSize > 0; position++) { token.ThrowIfCancellationRequested(); var scoreDoc = search.ScoreDocs[position]; global::Lucene.Net.Documents.Document document; using (luceneScope?.Start()) document = _searcher.Doc(scoreDoc.Doc, _state); if (retriever.TryGetKey(document, _state, out string key) && scope.WillProbablyIncludeInResults(key) == false) { skippedResults.Value++; continue; } var filterResult = queryFilter?.Apply(document, key, _state); if (filterResult is not null and not FilterResult.Accepted) { if (filterResult is FilterResult.Skipped) { continue; } if (filterResult is FilterResult.LimitReached) { break; } } bool markedAsSkipped = false; var r = retriever.Get(document, scoreDoc, _state, token); if (r.Document != null) { var qr = CreateQueryResult(r.Document); if (qr.Result == null) { continue; } yield return(qr); } else if (r.List != null) { int numberOfProjectedResults = 0; foreach (Document item in r.List) { var qr = CreateQueryResult(item); if (qr.Result == null) { continue; } yield return(qr); numberOfProjectedResults++; } if (numberOfProjectedResults > 1) { totalResults.Value += numberOfProjectedResults - 1; } } else { skippedResults.Value++; } QueryResult CreateQueryResult(Document d) { if (scope.TryIncludeInResults(d) == false) { d?.Dispose(); if (markedAsSkipped == false) { skippedResults.Value++; markedAsSkipped = true; } return(default);
/// <inheritdoc /> IDocumentQuery <T> IDocumentQueryBase <T, IDocumentQuery <T> > .IncludeExplanations(ExplanationOptions options, out Explanations explanations) { IncludeExplanations(options, out explanations); return(this); }