Esempio n. 1
0
 public JsonDocument RetrieveDocumentForQuery(IndexQueryResult queryResult, IndexDefinition indexDefinition, FieldsToFetch fieldsToFetch)
 {
     return(ExecuteReadTriggers(ProcessReadVetoes(
                                    RetrieveDocumentInternal(queryResult, loadedIdsForRetrieval, fieldsToFetch, indexDefinition),
                                    null, ReadOperation.Query), null, ReadOperation.Query));
 }
Esempio n. 2
0
        private JsonDocument RetrieveDocumentInternal(
            IndexQueryResult queryResult,
            HashSet <string> loadedIds,
            FieldsToFetch fieldsToFetch,
            IndexDefinition indexDefinition)
        {
            var queryScore = queryResult.Score;

            if (float.IsNaN(queryScore))
            {
                queryScore = 0f;
            }

            if (queryResult.Projection == null)
            {
                // duplicate document, filter it out
                if (loadedIds.Add(queryResult.Key) == false)
                {
                    return(null);
                }
                var document = GetDocumentWithCaching(queryResult.Key);
                if (document != null)
                {
                    document.Metadata[Constants.TemporaryScoreValue] = queryScore;
                }
                return(document);
            }

            JsonDocument doc = null;

            if (fieldsToFetch.IsProjection)
            {
                if (indexDefinition.IsMapReduce == false)
                {
                    bool         hasStoredFields = false;
                    FieldStorage value;
                    if (indexDefinition.Stores.TryGetValue(Constants.AllFields, out value))
                    {
                        hasStoredFields = value != FieldStorage.No;
                    }
                    foreach (var fieldToFetch in fieldsToFetch.Fields)
                    {
                        if (indexDefinition.Stores.TryGetValue(fieldToFetch, out value) == false && value != FieldStorage.No)
                        {
                            continue;
                        }
                        hasStoredFields = true;
                    }
                    if (hasStoredFields == false)
                    {
                        // duplicate document, filter it out
                        if (loadedIds.Add(queryResult.Key) == false)
                        {
                            return(null);
                        }
                    }
                }

                // We have to load the document if user explicitly asked for the id, since
                // we normalize the casing for the document id on the index, and we need to return
                // the id to the user with the same casing they gave us.
                var fetchingId = fieldsToFetch.HasField(Constants.DocumentIdFieldName);
                var fieldsToFetchFromDocument = fieldsToFetch.Fields.Where(fieldToFetch => queryResult.Projection[fieldToFetch] == null).ToArray();
                if (fieldsToFetchFromDocument.Length > 0 || fetchingId)
                {
                    doc = GetDocumentWithCaching(queryResult.Key);
                    if (doc != null)
                    {
                        if (fetchingId)
                        {
                            queryResult.Projection[Constants.DocumentIdFieldName] = doc.Key;
                        }

                        var result = doc.DataAsJson.SelectTokenWithRavenSyntax(fieldsToFetchFromDocument.ToArray());
                        foreach (var property in result)
                        {
                            if (property.Value == null || property.Value.Type == JTokenType.Null)
                            {
                                continue;
                            }
                            queryResult.Projection[property.Key] = property.Value;
                        }
                    }
                }
            }
            else if (fieldsToFetch.FetchAllStoredFields && string.IsNullOrEmpty(queryResult.Key) == false)
            {
                // duplicate document, filter it out
                if (loadedIds.Add(queryResult.Key) == false)
                {
                    return(null);
                }

                doc = GetDocumentWithCaching(queryResult.Key);
            }

            var metadata = GetMetadata(doc);

            metadata.Remove("@id");
            metadata[Constants.TemporaryScoreValue] = queryScore;
            return(new JsonDocument
            {
                Key = queryResult.Key,
                DataAsJson = queryResult.Projection,
                Metadata = metadata
            });
        }
Esempio n. 3
0
        private JsonDocument RetrieveDocumentInternal(
            IndexQueryResult queryResult,
            HashSet <string> loadedIds,
            FieldsToFetch fieldsToFetch,
            IndexDefinition indexDefinition)
        {
            if (queryResult.Projection == null)
            {
                // duplicate document, filter it out
                if (loadedIds.Add(queryResult.Key) == false)
                {
                    return(null);
                }
                var document = GetDocumentWithCaching(queryResult.Key);
                if (document != null)
                {
                    document.Metadata[Constants.TemporaryScoreValue] = queryResult.Score;
                }
                return(document);
            }

            if (fieldsToFetch.IsProjection)
            {
                if (indexDefinition.IsMapReduce == false)
                {
                    bool hasStoredFields = false;
                    foreach (var fieldToFetch in fieldsToFetch)
                    {
                        FieldStorage value;
                        if (indexDefinition.Stores.TryGetValue(fieldToFetch, out value) == false &&
                            value != FieldStorage.No)
                        {
                            continue;
                        }
                        hasStoredFields = true;
                    }
                    if (hasStoredFields == false)
                    {
                        // duplicate document, filter it out
                        if (loadedIds.Add(queryResult.Key) == false)
                        {
                            return(null);
                        }
                    }
                }
                var fieldsToFetchFromDocument = fieldsToFetch.Where(fieldToFetch => queryResult.Projection[fieldToFetch] == null);
                var doc = GetDocumentWithCaching(queryResult.Key);
                if (doc != null)
                {
                    var result = doc.DataAsJson.SelectTokenWithRavenSyntax(fieldsToFetchFromDocument.ToArray());
                    foreach (var property in result)
                    {
                        if (property.Value == null || property.Value.Type == JTokenType.Null)
                        {
                            continue;
                        }
                        queryResult.Projection[property.Key] = property.Value;
                    }
                }
            }

            return(new JsonDocument
            {
                Key = queryResult.Key,
                DataAsJson = queryResult.Projection,
                Metadata = new RavenJObject {
                    { Constants.TemporaryScoreValue, queryResult.Score }
                }
            });
        }
Esempio n. 4
0
        private JsonDocument RetrieveDocumentInternal(
            IndexQueryResult queryResult,
            HashSet <string> loadedIds,
            FieldsToFetch fieldsToFetch,
            IndexDefinition indexDefinition,
            bool skipDuplicateCheck)
        {
            var queryScore = queryResult.Score;

            if (float.IsNaN(queryScore))
            {
                queryScore = 0f;
            }

            if (queryResult.Projection == null)
            {
                // duplicate document, filter it out
                if (skipDuplicateCheck == false && loadedIds.Add(queryResult.Key) == false)
                {
                    return(null);
                }
                var document = GetDocumentWithCaching(queryResult);
                if (document == null)
                {
                    return(null);
                }

                document.Metadata = GetMetadata(document);

                if (skipDuplicateCheck == false)
                {
                    document.Metadata[Constants.TemporaryScoreValue] = queryScore;
                }

                return(document);
            }

            JsonDocument doc = null;

            if (fieldsToFetch.IsProjection)
            {
                if (indexDefinition.IsMapReduce == false)
                {
                    bool         hasStoredFields = false;
                    FieldStorage value;
                    if (indexDefinition.Stores.TryGetValue(Constants.AllFields, out value))
                    {
                        hasStoredFields = value != FieldStorage.No;
                    }
                    foreach (var fieldToFetch in fieldsToFetch.Fields)
                    {
                        if (indexDefinition.Stores.TryGetValue(fieldToFetch, out value) == false && value != FieldStorage.No)
                        {
                            continue;
                        }
                        hasStoredFields = true;
                    }
                    if (hasStoredFields == false)
                    {
                        // duplicate document, filter it out
                        if (loadedIds.Add(queryResult.Key) == false)
                        {
                            return(null);
                        }
                    }
                }

                // We have to load the document if user explicitly asked for the id, since
                // we normalize the casing for the document id on the index, and we need to return
                // the id to the user with the same casing they gave us.
                var fetchingId = fieldsToFetch.HasField(Constants.DocumentIdFieldName);
                var fieldsToFetchFromDocument = fieldsToFetch.Fields.Where(fieldToFetch => queryResult.Projection[fieldToFetch] == null).ToArray();
                if (fieldsToFetchFromDocument.Length > 0 || fetchingId)
                {
                    switch (configuration.ImplicitFetchFieldsFromDocumentMode)
                    {
                    case ImplicitFetchFieldsMode.Enabled:
                        doc = GetDocumentWithCaching(queryResult);
                        if (doc != null)
                        {
                            if (fetchingId)
                            {
                                queryResult.Projection[Constants.DocumentIdFieldName] = doc.Key;
                            }

                            var result = doc.DataAsJson.SelectTokenWithRavenSyntax(fieldsToFetchFromDocument.ToArray());
                            foreach (var property in result)
                            {
                                if (property.Value == null || property.Value.Type == JTokenType.Null)
                                {
                                    continue;
                                }
                                queryResult.Projection[property.Key] = property.Value;
                            }
                        }
                        break;

                    case ImplicitFetchFieldsMode.DoNothing:
                        break;

                    case ImplicitFetchFieldsMode.Exception:
                        string message = string.Format("Implicit fetching of fields from the document is disabled." + Environment.NewLine +
                                                       "Check your index ({0}) to make sure that all fields you want to project are stored in the index." + Environment.NewLine +
                                                       "You can control this behavior using the Raven/ImplicitFetchFieldsFromDocumentMode setting." + Environment.NewLine +
                                                       "Fields to fetch from document are: {1}" + Environment.NewLine +
                                                       "Fetching id: {2}", indexDefinition.Name, string.Join(", ", fieldsToFetchFromDocument), fetchingId);
                        throw new ImplicitFetchFieldsFromDocumentNotAllowedException(message);

                    default:
                        throw new ArgumentOutOfRangeException(configuration.ImplicitFetchFieldsFromDocumentMode.ToString());
                    }
                }
            }
            else if (fieldsToFetch.FetchAllStoredFields && string.IsNullOrEmpty(queryResult.Key) == false &&
                     (fieldsToFetch.Query == null || fieldsToFetch.Query.AllowMultipleIndexEntriesForSameDocumentToResultTransformer == false)
                     )
            {
                // duplicate document, filter it out
                if (loadedIds.Add(queryResult.Key) == false)
                {
                    return(null);
                }

                doc = GetDocumentWithCaching(queryResult);
            }

            var metadata = GetMetadata(doc);

            metadata.Remove("@id");
            metadata[Constants.TemporaryScoreValue] = queryScore;
            return(new JsonDocument
            {
                Key = queryResult.Key,
                DataAsJson = queryResult.Projection,
                Metadata = metadata
            });
        }
Esempio n. 5
0
        private JsonDocument RetrieveDocumentInternal(
            IndexQueryResult queryResult,
            HashSet <string> loadedIds,
            IEnumerable <string> fieldsToFetch,
            IndexDefinition indexDefinition,
            AggregationOperation aggregationOperation)
        {
            if (queryResult.Projection == null)
            {
                // duplicate document, filter it out
                if (loadedIds.Add(queryResult.Key) == false)
                {
                    return(null);
                }
                return(GetDocumentWithCaching(queryResult.Key));
            }

            if (fieldsToFetch != null)
            {
                if (indexDefinition.IsMapReduce == false)
                {
                    bool hasStoredFields = false;
                    foreach (var fieldToFetch in fieldsToFetch)
                    {
                        FieldStorage value;
                        if (indexDefinition.Stores.TryGetValue(fieldToFetch, out value) == false &&
                            value != FieldStorage.No)
                        {
                            continue;
                        }
                        hasStoredFields = true;
                    }
                    if (hasStoredFields == false)
                    {
                        // duplicate document, filter it out
                        if (loadedIds.Add(queryResult.Key) == false)
                        {
                            return(null);
                        }
                    }
                }
                if (aggregationOperation != AggregationOperation.None)
                {
                    var aggOpr = aggregationOperation & ~AggregationOperation.Dynamic;
                    fieldsToFetch = fieldsToFetch.Concat(new[] { aggOpr.ToString() });
                }
                var fieldsToFetchFromDocument = fieldsToFetch.Where(fieldToFetch => queryResult.Projection.Property(fieldToFetch) == null);
                var doc = GetDocumentWithCaching(queryResult.Key);
                if (doc != null)
                {
                    var result = doc.DataAsJson.SelectTokenWithRavenSyntax(fieldsToFetchFromDocument.ToArray());
                    foreach (var property in result.Properties())
                    {
                        if (property.Value == null || property.Value.Type == JTokenType.Null)
                        {
                            continue;
                        }
                        queryResult.Projection[property.Name] = property.Value;
                    }
                }
            }

            return(new JsonDocument
            {
                Key = queryResult.Key,
                Projection = queryResult.Projection,
            });
        }
Esempio n. 6
0
            public IEnumerable <IndexQueryResult> IntersectionQuery()
            {
                using (IndexStorage.EnsureInvariantCulture())
                {
                    AssertQueryDoesNotContainFieldsThatAreNotIndexes();
                    IndexSearcher indexSearcher;
                    using (parent.GetSearcher(out indexSearcher))
                    {
                        int pageSizeBestGuess           = (indexQuery.Start + indexQuery.PageSize) * 2;
                        int returnedResults             = 0;
                        int skippedResultsInCurrentLoop = 0;
                        int previousIntersectMatches    = 0;

                        var subQueries = indexQuery.Query.Split(new[] { Constants.IntersectSeperator }, StringSplitOptions.RemoveEmptyEntries);
                        if (subQueries.Length <= 1)
                        {
                            throw new InvalidOperationException("Invalid INTRESECT query, must have multiple intersect clauses.");
                        }

                        //Do the first sub-query in the normal way, so that sorting, filtering etc is accounted for
                        var firstSubLuceneQuery = ApplyIndexTriggers(GetLuceneQuery(subQueries[0]));

                        //Not sure how to select the page size here??? The problem is that only docs in this search can be part
                        //of the final result because we're doing an intersection query (but we might exclude some of them)
                        var search = ExecuteQuery(indexSearcher, firstSubLuceneQuery, 0, pageSizeBestGuess, indexQuery);
                        var intersectionCollector = new IntersectionCollector(indexSearcher, search.ScoreDocs);
                        var intersectMatches      = 0;

                        //Keep going until we've pulled through enough intersecting docs to satisfy pageSize + start
                        //OR the current loop doesn't get us any more results, despite increasing the page size
                        do
                        {
                            if (skippedResultsInCurrentLoop > 0)
                            {
                                // We get here because out first attempt didn't get enough docs (after INTERSECTION was calculated)
                                pageSizeBestGuess = pageSizeBestGuess * 2;

                                search = ExecuteQuery(indexSearcher, firstSubLuceneQuery, 0, pageSizeBestGuess, indexQuery);
                                intersectionCollector = new IntersectionCollector(indexSearcher, search.ScoreDocs);
                            }

                            Filter filter = indexQuery.GetFilter();
                            for (int i = 1; i < subQueries.Length; i++)
                            {
                                var luceneSubQuery = ApplyIndexTriggers(GetLuceneQuery(subQueries[i]));
                                indexSearcher.Search(luceneSubQuery, filter, intersectionCollector);
                            }

                            var currentIntersectResults = intersectionCollector.DocumentsIdsForCount(subQueries.Length).ToList();
                            previousIntersectMatches    = intersectMatches;
                            intersectMatches            = currentIntersectResults.Count;
                            skippedResultsInCurrentLoop = pageSizeBestGuess - intersectMatches;
                        } while (previousIntersectMatches < intersectMatches && intersectMatches < indexQuery.PageSize);

                        var intersectResults = intersectionCollector.DocumentsIdsForCount(subQueries.Length).ToList();
                        //It's hard to know what to do here, the TotalHits from the base search isn't really the TotalSize,
                        //because it's before the INTERSECTION has been applied, so only some of those results make it out.
                        //Trying to give an accurate answer is going to be too costly, so we aren't going to try.
                        indexQuery.TotalSize.Value      = search.TotalHits;
                        indexQuery.SkippedResults.Value = skippedResultsInCurrentLoop;

                        //Using the final set of results in the intersectionCollector
                        for (int i = indexQuery.Start; i < intersectResults.Count && (i - indexQuery.Start) < pageSizeBestGuess; i++)
                        {
                            Document         document         = indexSearcher.Doc(intersectResults[i].LuceneId);
                            IndexQueryResult indexQueryResult = parent.RetrieveDocument(document, fieldsToFetch, search.ScoreDocs[i].score);
                            if (ShouldIncludeInResults(indexQueryResult) == false)
                            {
                                indexQuery.SkippedResults.Value++;
                                skippedResultsInCurrentLoop++;
                                continue;
                            }
                            returnedResults++;
                            yield return(indexQueryResult);

                            if (returnedResults == indexQuery.PageSize)
                            {
                                yield break;
                            }
                        }
                    }
                }
            }