예제 #1
0
        private void ExecuteQueryOperation(IndexQueryServerSide query,
                                           Func <QueryRunner,
                                                 QueryOperationOptions,
                                                 Action <IOperationProgress>, OperationCancelToken,
                                                 Task <IOperationResult> > operation,
                                           DocumentsOperationContext context,
                                           IDisposable returnContextToPool,
                                           Operations.Operations.OperationType operationType)
        {
            var options = GetQueryOperationOptions();
            var token   = CreateTimeLimitedQueryOperationToken();

            var operationId = Database.Operations.GetNextOperationId();

            var indexName = query.Metadata.IsDynamic
                ? (query.Metadata.IsCollectionQuery ? "collection/" : "dynamic/") + query.Metadata.CollectionName
                : query.Metadata.IndexName;

            var details = new BulkOperationResult.OperationDetails
            {
                Query = query.Query
            };

            var task = Database.Operations.AddOperation(Database, indexName, operationType,
                                                        onProgress => operation(Database.QueryRunner, options, onProgress, token), operationId, details, token);

            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                writer.WriteOperationId(context, operationId);
            }

            task.ContinueWith(_ =>
            {
                using (returnContextToPool)
                    token.Dispose();
            });
        }
예제 #2
0
        public async Task Patch()
        {
            var queryContext = QueryOperationContext.Allocate(Database); // we don't dispose this as operation is async

            try
            {
                var reader = await queryContext.Documents.ReadForMemoryAsync(RequestBodyStream(), "queries/patch");

                if (reader == null)
                {
                    throw new BadRequestException("Missing JSON content.");
                }
                if (reader.TryGet("Query", out BlittableJsonReaderObject queryJson) == false || queryJson == null)
                {
                    throw new BadRequestException("Missing 'Query' property.");
                }

                var query = IndexQueryServerSide.Create(HttpContext, queryJson, Database.QueryMetadataCache, null, queryType: QueryType.Update);

                if (TrafficWatchManager.HasRegisteredClients)
                {
                    TrafficWatchQuery(query);
                }

                var patch = new PatchRequest(query.Metadata.GetUpdateBody(query.QueryParameters), PatchRequestType.Patch, query.Metadata.DeclaredFunctions);

                await ExecuteQueryOperation(query,
                                            (runner, options, onProgress, token) => runner.ExecutePatchQuery(
                                                query, options, patch, query.QueryParameters, queryContext, onProgress, token),
                                            queryContext, Operations.Operations.OperationType.UpdateByQuery);
            }
            catch
            {
                queryContext.Dispose();
                throw;
            }
        }
예제 #3
0
        public async Task <DocumentQueryResult> Execute(IndexQueryServerSide query, long?existingResultEtag)
        {
            var tuple = await MatchIndex(query, true);

            var index      = tuple.Index;
            var collection = tuple.Collection;

            if (index == null)
            {
                var result = new DocumentQueryResult();
                _context.OpenReadTransaction();
                FillCountOfResultsAndIndexEtag(result, collection);

                if (existingResultEtag.HasValue)
                {
                    if (result.ResultEtag == existingResultEtag)
                    {
                        return(DocumentQueryResult.NotModifiedResult);
                    }
                }

                ExecuteCollectionQuery(result, query, collection);

                return(result);
            }

            if (existingResultEtag.HasValue)
            {
                var etag = index.GetIndexEtag();
                if (etag == existingResultEtag)
                {
                    return(DocumentQueryResult.NotModifiedResult);
                }
            }

            return(await index.Query(query, _context, _token));
        }
예제 #4
0
        public Task Delete()
        {
            var returnContextToPool = ContextPool.AllocateOperationContext(out DocumentsOperationContext context); // we don't dispose this as operation is async

            var reader = context.Read(RequestBodyStream(), "queries/delete");
            var query  = IndexQueryServerSide.Create(reader, context, Database.QueryMetadataCache);

            if (query.Metadata.IsDynamic == false)
            {
                ExecuteQueryOperation(query,
                                      (runner, options, onProgress, token) => runner.Query.ExecuteDeleteQuery(query, options.Query, context, onProgress, token),
                                      context, returnContextToPool, Operations.Operations.OperationType.DeleteByIndex);
            }
            else
            {
                EnsureQueryHasOnlyFromClause(query.Metadata, query.Metadata.CollectionName);

                ExecuteQueryOperation(query,
                                      (runner, options, onProgress, token) => runner.Collection.ExecuteDelete(query.Metadata.CollectionName, options.Collection, onProgress, token),
                                      context, returnContextToPool, Operations.Operations.OperationType.DeleteByCollection);
            }

            return(Task.CompletedTask);
        }
예제 #5
0
        private Index MatchIndex(string dynamicIndexName, IndexQueryServerSide query, bool createAutoIndexIfNoMatchIsFound, out string collection)
        {
            collection = dynamicIndexName.Length == DynamicIndex.Length
                ? Constants.Indexing.AllDocumentsCollection
                : dynamicIndexName.Substring(DynamicIndexPrefix.Length);

            var map = DynamicQueryMapping.Create(collection, query);

            if (map.MapFields.Length == 0 && map.SortDescriptors.Length == 0 && map.GroupByFields.Length == 0)
            {
                return(null); // use collection query
            }
            Index index;

            if (TryMatchExistingIndexToQuery(map, out index) == false)
            {
                if (createAutoIndexIfNoMatchIsFound == false)
                {
                    throw new IndexDoesNotExistsException("Could not find index for a given query.");
                }

                var definition = map.CreateAutoIndexDefinition();

                var id = _indexStore.CreateIndex(definition);
                index = _indexStore.GetIndex(id);

                if (query.WaitForNonStaleResultsTimeout.HasValue == false)
                {
                    query.WaitForNonStaleResultsTimeout = TimeSpan.FromSeconds(15); // allow new auto indexes to have some results
                }
            }

            EnsureValidQuery(query, map);

            return(index);
        }
예제 #6
0
        private async Task FacetedQuery(IndexQueryServerSide indexQuery, DocumentsOperationContext context, OperationCancelToken token)
        {
            var existingResultEtag = GetLongFromHeaders("If-None-Match");

            var result = await Database.QueryRunner.ExecuteFacetedQuery(indexQuery, existingResultEtag, context, token);

            if (result.NotModified)
            {
                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                return;
            }

            HttpContext.Response.Headers[Constants.Headers.Etag] = CharExtensions.ToInvariantString(result.ResultEtag);

            int numberOfResults;

            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                writer.WriteFacetedQueryResult(context, result, numberOfResults: out numberOfResults);
            }

            Database.QueryMetadataCache.MaybeAddToCache(indexQuery.Metadata, result.IndexName);
            AddPagingPerformanceHint(PagingOperationType.Queries, $"{nameof(FacetedQuery)} ({result.IndexName})", indexQuery.Query, numberOfResults, indexQuery.PageSize, result.DurationInMs);
        }
예제 #7
0
        protected IEnumerable <Document> GetDocuments(DocumentsOperationContext context, string collectionName, long startEtag, long start, int batchSize, bool isAllDocs, DocumentFields fields)
        {
            if (_collectionQuery != null && _collectionQuery.Metadata.WhereFields.Count > 0)
            {
                if (_operationQuery == null)
                {
                    _operationQuery = ConvertToOperationQuery(_collectionQuery, batchSize);
                }

                return(new CollectionQueryEnumerable(Database, Database.DocumentsStorage, new FieldsToFetch(_operationQuery, null),
                                                     collectionName, _operationQuery, null, context, null, null, new Reference <int>())
                {
                    Fields = fields,
                    InternalQueryOperationStart = start
                });
            }

            if (isAllDocs)
            {
                return(Database.DocumentsStorage.GetDocumentsFrom(context, startEtag, 0, batchSize, fields));
            }

            return(Database.DocumentsStorage.GetDocumentsFrom(context, collectionName, startEtag, 0, batchSize, fields));
        }
예제 #8
0
        private static string GetLuceneQuery(IndexQuery indexQuery, JsonOperationContext context, JsonSerializer jsonSerializer)
        {
            using (var writer = new BlittableJsonWriter(context))
            {
                jsonSerializer.Serialize(writer, indexQuery.QueryParameters);

                writer.FinalizeDocument();

                using (var blittableParameters = writer.CreateReader())
                {
                    var indexQueryServerSide = new IndexQueryServerSide(indexQuery.Query, blittableParameters);

                    var luceneQuery = QueryBuilder.BuildQuery(null,
                                                              null,
                                                              indexQueryServerSide.Metadata,
                                                              indexQueryServerSide.Metadata.Query.Where,
                                                              null,
                                                              blittableParameters, null,
                                                              null);

                    return(luceneQuery.ToString());
                }
            }
        }
예제 #9
0
        private void Explain(DocumentsOperationContext context, string indexName)
        {
            var indexQuery = IndexQueryServerSide.Create(HttpContext, GetStart(), GetPageSize(Database.Configuration.Core.MaxPageSize), context);
            var runner     = new QueryRunner(Database, context);

            var explanations = runner.ExplainDynamicIndexSelection(indexName, indexQuery);

            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                var isFirst = true;
                writer.WriteStartArray();
                foreach (var explanation in explanations)
                {
                    if (isFirst == false)
                    {
                        writer.WriteComma();
                    }

                    isFirst = false;
                    writer.WriteExplanation(context, explanation);
                }
                writer.WriteEndArray();
            }
        }
예제 #10
0
 public async Task StreamQueryGet()
 {
     // ReSharper disable once ArgumentsStyleLiteral
     using (TrackRequestTime("StreamQuery", doPerformanceHintIfTooLong: false))
         using (var token = CreateTimeLimitedOperationToken())
             using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
             {
                 var query           = IndexQueryServerSide.Create(HttpContext, GetStart(), GetPageSize(), context);
                 var properties      = GetStringValuesQueryString("field", false);
                 var propertiesArray = properties.Count == 0 ? null : properties.ToArray();
                 using (var writer = new StreamCsvDocumentQueryResultWriter(HttpContext.Response, ResponseBodyStream(), context, propertiesArray))
                 {
                     try
                     {
                         await Database.QueryRunner.ExecuteStreamQuery(query, context, HttpContext.Response, writer, token).ConfigureAwait(false);
                     }
                     catch (IndexDoesNotExistException)
                     {
                         HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                         writer.WriteError("Index " + query.Metadata.IndexName + " does not exists");
                     }
                 }
             }
 }
예제 #11
0
        private static void UpdateFacetResults(Dictionary <string, FacetedQueryParser.FacetResult> results, IndexQueryServerSide query, Dictionary <string, Dictionary <string, FacetValue> > facetsByName)
        {
            foreach (var result in results)
            {
                if (result.Value.Ranges != null && result.Value.Ranges.Count > 0)
                {
                    continue;
                }

                var           values = new List <FacetValue>();
                List <string> allTerms;
                if (facetsByName.TryGetValue(result.Key, out Dictionary <string, FacetValue> groups) == false || groups == null)
                {
                    continue;
                }

                switch (result.Value.Options.TermSortMode)
                {
                case FacetTermSortMode.ValueAsc:
                    allTerms = new List <string>(groups.OrderBy(x => x.Key).ThenBy(x => x.Value.Count).Select(x => x.Key));
                    break;

                case FacetTermSortMode.ValueDesc:
                    allTerms = new List <string>(groups.OrderByDescending(x => x.Key).ThenBy(x => x.Value.Count).Select(x => x.Key));
                    break;

                case FacetTermSortMode.CountAsc:
                    allTerms = new List <string>(groups.OrderBy(x => x.Value.Count).ThenBy(x => x.Key).Select(x => x.Key));
                    break;

                case FacetTermSortMode.CountDesc:
                    allTerms = new List <string>(groups.OrderByDescending(x => x.Value.Count).ThenBy(x => x.Key).Select(x => x.Key));
                    break;

                default:
                    throw new ArgumentException(string.Format("Could not understand '{0}'", result.Value.Options.TermSortMode));
                }

                var start    = result.Value.Options.Start;
                var pageSize = Math.Min(allTerms.Count, result.Value.Options.PageSize);

                foreach (var term in allTerms.Skip(start).TakeWhile(term => values.Count < pageSize))
                {
                    if (groups.TryGetValue(term, out FacetValue facetValue) == false || facetValue == null)
                    {
                        facetValue = new FacetValue {
                            Range = term
                        }
                    }
                    ;

                    values.Add(facetValue);
                }

                var previousHits = allTerms.Take(start).Sum(allTerm =>
                {
                    if (groups.TryGetValue(allTerm, out FacetValue facetValue) == false || facetValue == null)
                    {
                        return(0);
                    }

                    return(facetValue.Count);
                });

                result.Value.Result = new FacetResult
                {
                    Name   = result.Key,
                    Values = values,
                    RemainingTermsCount = allTerms.Count - (start + values.Count),
                    RemainingHits       = groups.Values.Sum(x => x.Count) - (previousHits + values.Sum(x => x.Count))
                };

                if (result.Value.Options.IncludeRemainingTerms)
                {
                    result.Value.Result.RemainingTerms = allTerms.Skip(start + values.Count).ToList();
                }
            }
        }
예제 #12
0
 public override IQueryResultRetriever GetQueryResultRetriever(IndexQueryServerSide query, DocumentsOperationContext documentsContext, FieldsToFetch fieldsToFetch, IncludeDocumentsCommand includeDocumentsCommand)
 {
     throw new NotSupportedException($"Index {Name} is in-memory implementation of a faulty index", _e);
 }
예제 #13
0
 public override Task <DocumentQueryResult> Query(IndexQueryServerSide query, DocumentsOperationContext documentsContext, OperationCancelToken token)
 {
     throw new NotSupportedException($"Index {Name} is in-memory implementation of a faulty index", _e);
 }
예제 #14
0
 public override Task StreamQuery(HttpResponse response, IStreamDocumentQueryResultWriter writer, IndexQueryServerSide query, DocumentsOperationContext documentsContext, OperationCancelToken token)
 {
     throw new NotSupportedException($"Index {Name} is in-memory implementation of a faulty index", _e);
 }
예제 #15
0
        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;
                }
            }
        }
예제 #16
0
        public override async Task <IOperationResult> ExecuteDeleteQuery(IndexQueryServerSide query, QueryOperationOptions options, DocumentsOperationContext context, Action <IOperationProgress> onProgress, OperationCancelToken token)
        {
            var index = await MatchIndex(query, true, null, context, token.Token);

            return(await ExecuteDelete(query, index, options, context, onProgress, token));
        }
예제 #17
0
        private void ExecuteCollectionQuery(QueryResultServerSide <Document> resultToFill, IndexQueryServerSide query, string collection, DocumentsOperationContext context, CancellationToken cancellationToken)
        {
            using (var queryScope = query.Timings?.For(nameof(QueryTimingsScope.Names.Query)))
            {
                QueryTimingsScope gatherScope = null;
                QueryTimingsScope fillScope   = null;

                if (queryScope != null && query.Metadata.Includes?.Length > 0)
                {
                    var includesScope = queryScope.For(nameof(QueryTimingsScope.Names.Includes), start: false);
                    gatherScope = includesScope.For(nameof(QueryTimingsScope.Names.Gather), start: false);
                    fillScope   = includesScope.For(nameof(QueryTimingsScope.Names.Fill), start: false);
                }

                var isAllDocsCollection = collection == Constants.Documents.Collections.AllDocumentsCollection;

                // we optimize for empty queries without sorting options, appending CollectionIndexPrefix to be able to distinguish index for collection vs. physical index
                resultToFill.IndexName      = isAllDocsCollection ? "AllDocs" : CollectionIndexPrefix + collection;
                resultToFill.IsStale        = false;
                resultToFill.LastQueryTime  = DateTime.MinValue;
                resultToFill.IndexTimestamp = DateTime.MinValue;
                resultToFill.IncludedPaths  = query.Metadata.Includes;

                var fieldsToFetch           = new FieldsToFetch(query, null);
                var includeDocumentsCommand = new IncludeDocumentsCommand(Database.DocumentsStorage, context, query.Metadata.Includes, fieldsToFetch.IsProjection);
                var totalResults            = new Reference <int>();
                var documents = new CollectionQueryEnumerable(Database, Database.DocumentsStorage, fieldsToFetch, collection, query, queryScope, context, includeDocumentsCommand, totalResults);
                IncludeCountersCommand includeCountersCommand = null;
                if (query.Metadata.HasCounters)
                {
                    includeCountersCommand = new IncludeCountersCommand(
                        Database,
                        context,
                        query.Metadata.CounterIncludes.Counters);
                }

                try
                {
                    foreach (var document in documents)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        resultToFill.AddResult(document);

                        using (gatherScope?.Start())
                            includeDocumentsCommand.Gather(document);

                        includeCountersCommand?.Fill(document);
                    }
                }
                catch (Exception e)
                {
                    if (resultToFill.SupportsExceptionHandling == false)
                    {
                        throw;
                    }

                    resultToFill.HandleException(e);
                }

                using (fillScope?.Start())
                    includeDocumentsCommand.Fill(resultToFill.Includes);

                if (includeCountersCommand != null)
                {
                    resultToFill.AddCounterIncludes(includeCountersCommand);
                }

                resultToFill.TotalResults = (totalResults.Value == 0 && resultToFill.Results.Count != 0) ? -1 : totalResults.Value;
            }
        }
예제 #18
0
 public override Task <IndexEntriesQueryResult> ExecuteIndexEntriesQuery(IndexQueryServerSide query, DocumentsOperationContext context, long?existingResultEtag, OperationCancelToken token)
 {
     throw new NotSupportedException("Collection query is handled directly by documents storage so index entries aren't created underneath");
 }
예제 #19
0
        public Task PatchTest()
        {
            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
            {
                var reader = context.Read(RequestBodyStream(), "queries/patch");
                if (reader == null)
                {
                    throw new BadRequestException("Missing JSON content.");
                }
                if (reader.TryGet("Query", out BlittableJsonReaderObject queryJson) == false || queryJson == null)
                {
                    throw new BadRequestException("Missing 'Query' property.");
                }

                var query = IndexQueryServerSide.Create(HttpContext, queryJson, Database.QueryMetadataCache, null, QueryType.Update);

                if (TrafficWatchManager.HasRegisteredClients)
                {
                    TrafficWatchQuery(query);
                }

                var patch = new PatchRequest(query.Metadata.GetUpdateBody(query.QueryParameters), PatchRequestType.Patch, query.Metadata.DeclaredFunctions);

                var docId = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id");

                var command = new PatchDocumentCommand(context, docId,
                                                       expectedChangeVector: null,
                                                       skipPatchIfChangeVectorMismatch: false,
                                                       patch: (patch, query.QueryParameters),
                                                       patchIfMissing: (null, null),
                                                       database: context.DocumentDatabase,
                                                       debugMode: true,
                                                       isTest: true,
                                                       collectResultsNeeded: true,
                                                       returnDocument: false);

                using (context.OpenWriteTransaction())
                {
                    command.Execute(context, null);
                }

                switch (command.PatchResult.Status)
                {
                case PatchStatus.DocumentDoesNotExist:
                    HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    return(Task.CompletedTask);

                case PatchStatus.Created:
                    HttpContext.Response.StatusCode = (int)HttpStatusCode.Created;
                    break;

                case PatchStatus.Skipped:
                    HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                    return(Task.CompletedTask);

                case PatchStatus.Patched:
                case PatchStatus.NotModified:
                    HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                WritePatchResultToResponse(context, command);

                return(Task.CompletedTask);
            }
        }
예제 #20
0
        private async Task <Index> MatchIndex(IndexQueryServerSide query, bool createAutoIndexIfNoMatchIsFound, TimeSpan?customStalenessWaitTimeout, DocumentsOperationContext docsContext,
                                              CancellationToken token)
        {
            Index index;

            if (query.Metadata.AutoIndexName != null)
            {
                index = _indexStore.GetIndex(query.Metadata.AutoIndexName);

                if (index != null)
                {
                    return(index);
                }
            }

            var map = DynamicQueryMapping.Create(query);

            if (TryMatchExistingIndexToQuery(map, docsContext, out index) == false)
            {
                if (createAutoIndexIfNoMatchIsFound == false)
                {
                    throw new IndexDoesNotExistException("Could not find index for a given query.");
                }

                var definition = map.CreateAutoIndexDefinition();

                index = await _indexStore.CreateIndex(definition);

                if (query.WaitForNonStaleResultsTimeout.HasValue == false)
                {
                    if (customStalenessWaitTimeout.HasValue)
                    {
                        query.WaitForNonStaleResultsTimeout = customStalenessWaitTimeout.Value;
                    }
                    else
                    {
                        query.WaitForNonStaleResultsTimeout = TimeSpan.FromSeconds(15); // allow new auto indexes to have some results
                    }
                }

                var t = CleanupSupercededAutoIndexes(index, map, token)
                        .ContinueWith(task =>
                {
                    if (task.Exception != null)
                    {
                        if (token.IsCancellationRequested)
                        {
                            return;
                        }

                        if (_indexStore.Logger.IsInfoEnabled)
                        {
                            _indexStore.Logger.Info("Failed to delete superceded indexes for index " + index.Name);
                        }
                    }
                });

                if (query.WaitForNonStaleResults &&
                    Database.Configuration.Indexing.TimeToWaitBeforeDeletingAutoIndexMarkedAsIdle.AsTimeSpan ==
                    TimeSpan.Zero)
                {
                    await t; // this is used in testing, mainly
                }
            }

            return(index);
        }
예제 #21
0
        public override async Task <IOperationResult> ExecutePatchQuery(IndexQueryServerSide query, QueryOperationOptions options, PatchRequest patch, BlittableJsonReaderObject patchArgs, DocumentsOperationContext context, Action <IOperationProgress> onProgress, OperationCancelToken token)
        {
            var index = await MatchIndex(query, true, null, context, token.Token);

            return(await ExecutePatch(query, index, options, patch, patchArgs, context, onProgress, token));
        }
예제 #22
0
 public MapQueryResultRetriever(DocumentDatabase database, IndexQueryServerSide query, QueryTimingsScope queryTimings, DocumentsStorage documentsStorage, DocumentsOperationContext context, FieldsToFetch fieldsToFetch, IncludeDocumentsCommand includeDocumentsCommand, IncludeCompareExchangeValuesCommand includeCompareExchangeValuesCommand, IncludeRevisionsCommand includeRevisionsCommand)
     : base(database, query, queryTimings, fieldsToFetch, documentsStorage, context, false, includeDocumentsCommand, includeCompareExchangeValuesCommand, includeRevisionsCommand: includeRevisionsCommand)
 {
     _context = context;
 }
예제 #23
0
 private FacetQuery(IndexQueryServerSide query, Dictionary <string, FacetSetup> facets, long facetsEtag)
 {
     Query      = query;
     Facets     = facets;
     FacetsEtag = facetsEtag;
 }
예제 #24
0
 private void ExecuteQueryOperation(IndexQueryServerSide query,
                                    Func <(QueryRunner Query, CollectionRunner Collection),
        public static void WriteIndexQuery(this BlittableJsonTextWriter writer, JsonOperationContext context, IndexQueryServerSide query)
        {
            writer.WriteStartObject();

            writer.WritePropertyName(nameof(query.CutoffEtag));
            if (query.CutoffEtag.HasValue)
            {
                writer.WriteInteger(query.CutoffEtag.Value);
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(query.ExplainScores));
            writer.WriteBool(query.ExplainScores);
            writer.WriteComma();

            writer.WritePropertyName(nameof(query.PageSize));
            writer.WriteInteger(query.PageSize);
            writer.WriteComma();

            writer.WritePropertyName(nameof(query.Query));
            if (query.Query != null)
            {
                writer.WriteString(query.Query);
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(query.ShowTimings));
            writer.WriteBool(query.ShowTimings);
            writer.WriteComma();

            writer.WritePropertyName(nameof(query.SkipDuplicateChecking));
            writer.WriteBool(query.SkipDuplicateChecking);
            writer.WriteComma();

            writer.WritePropertyName(nameof(query.Start));
            writer.WriteInteger(query.Start);
            writer.WriteComma();

            writer.WritePropertyName(nameof(query.WaitForNonStaleResults));
            writer.WriteBool(query.WaitForNonStaleResults);
            writer.WriteComma();

            writer.WritePropertyName(nameof(query.WaitForNonStaleResultsTimeout));
            if (query.WaitForNonStaleResultsTimeout.HasValue)
            {
                writer.WriteString(query.WaitForNonStaleResultsTimeout.Value.ToString());
            }
            else
            {
                writer.WriteNull();
            }

            writer.WriteEndObject();
        }
예제 #26
0
        public override async Task <IndexEntriesQueryResult> ExecuteIndexEntriesQuery(IndexQueryServerSide query, DocumentsOperationContext context, long?existingResultEtag, OperationCancelToken token)
        {
            var index = await MatchIndex(query, false, null, context, token.Token);

            if (index == null)
            {
                IndexDoesNotExistException.ThrowFor(query.Metadata.CollectionName);
            }

            if (existingResultEtag.HasValue)
            {
                var etag = index.GetIndexEtag();
                if (etag == existingResultEtag)
                {
                    return(IndexEntriesQueryResult.NotModifiedResult);
                }
            }

            return(index.IndexEntries(query, context, token));
        }
예제 #27
0
 public override Task ExecuteStreamIndexEntriesQuery(IndexQueryServerSide query, DocumentsOperationContext documentsContext, HttpResponse response,
                                                     IStreamQueryResultWriter <BlittableJsonReaderObject> writer, OperationCancelToken token)
 {
     throw new NotSupportedException("Collection query is handled directly by documents storage so index entries aren't created underneath");
 }
예제 #28
0
 public override Task StreamQuery(HttpResponse response, BlittableJsonTextWriter writer, IndexQueryServerSide query, DocumentsOperationContext documentsContext, OperationCancelToken token)
 {
     throw new NotSupportedException($"Index with id {IndexId} is in-memory implementation of a faulty index", _e);
 }
예제 #29
0
 public override IQueryResultRetriever GetQueryResultRetriever(IndexQueryServerSide query, QueryTimingsScope queryTimings, DocumentsOperationContext documentsContext, FieldsToFetch fieldsToFetch, IncludeDocumentsCommand includeDocumentsCommand)
 {
     return(new MapQueryResultRetriever(DocumentDatabase, query, queryTimings, DocumentDatabase.DocumentsStorage, documentsContext, fieldsToFetch, includeDocumentsCommand));
 }
예제 #30
0
 public override IQueryResultRetriever GetQueryResultRetriever(IndexQueryServerSide query, QueryTimingsScope queryTimings, DocumentsOperationContext documentsContext, FieldsToFetch fieldsToFetch,
                                                               IncludeDocumentsCommand includeDocumentsCommand)
 {
     throw new NotImplementedException();
 }