Exemple #1
0
		public CurrentTransformationScope(DocumentDatabase database, DocumentRetriever documentRetriever)
		{
			this.database = database;
			retriever = documentRetriever;
			old = current;
			current = this;

		}
Exemple #2
0
        public bool IndexDocuments(IStorageActionsAccessor actions, string index, Guid etagToIndexFrom)
        {
            log.DebugFormat("Indexing documents for {0}, etag to index from: {1}", index, etagToIndexFrom);
            var viewGenerator = context.IndexDefinitionStorage.GetViewGenerator(index);
            if (viewGenerator == null)
                return false; // index was deleted, probably

            var jsonDocs = actions.Documents.GetDocumentsAfter(etagToIndexFrom)
                .Where(x => x != null)
                .Take(10000) // ensure that we won't go overboard with reading and blow up with OOM
                .ToArray();

            if(jsonDocs.Length == 0)
                return false;

            var dateTime = jsonDocs.Select(x=>x.LastModified).Min();

            var documentRetriever = new DocumentRetriever(null, context.ReadTriggers);
            try
            {
                log.DebugFormat("Indexing {0} documents for index: {1}", jsonDocs.Length, index);
                context.IndexStorage.Index(index, viewGenerator,
                    jsonDocs
                    .Select(doc => documentRetriever.ProcessReadVetoes(doc, null, ReadOperation.Index))
                    .Where(doc => doc != null)
                    .Select(x => JsonToExpando.Convert(x.ToJson())), context, actions, dateTime);

                return true;
            }
            catch (Exception e)
            {
                log.WarnFormat(e, "Failed to index documents for index: {0}", index);
                return false;
            }
            finally
            {
                // whatever we succeeded in indexing or not, we have to update this
                // because otherwise we keep trying to re-index failed documents
                var last = jsonDocs.Last();
                actions.Indexing.UpdateLastIndexed(index, last.Etag, last.LastModified);
            }
        }
Exemple #3
0
			public void Init()
			{
				highlightings = new Dictionary<string, Dictionary<string, string[]>>();
				scoreExplanations = new Dictionary<string, string>();
				Func<IndexQueryResult, object> tryRecordHighlightingAndScoreExplanation = queryResult =>
				{
                  
                    if (queryResult.Highligtings != null && (queryResult.Key != null || queryResult.HighlighterKey != null))
						highlightings.Add(queryResult.Key ?? queryResult.HighlighterKey, queryResult.Highligtings);
                    if ((queryResult.Key != null || queryResult.ReduceVal != null) && queryResult.ScoreExplanation != null)
						scoreExplanations.Add(queryResult.Key ?? queryResult.ReduceVal, queryResult.ScoreExplanation);
					return null;
				};
				stale = false;
				indexTimestamp = Tuple.Create(DateTime.MinValue, Etag.Empty);
				resultEtag = Etag.Empty;
				nonAuthoritativeInformation = false;

				if (string.IsNullOrEmpty(query.ResultsTransformer) == false &&
					(query.FieldsToFetch == null || query.FieldsToFetch.Length == 0))
				{
					query.FieldsToFetch = new[] { Constants.AllFields };
				}

				duration = Stopwatch.StartNew();
				idsToLoad = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

				var viewGenerator = database.IndexDefinitionStorage.GetViewGenerator(indexName);
				var index = database.IndexDefinitionStorage.GetIndexDefinition(indexName);
				if (viewGenerator == null)
					throw new IndexDoesNotExistsException("Could not find index named: " + indexName);

				resultEtag = database.Indexes.GetIndexEtag(index.Name, null, query.ResultsTransformer);

				stale = actions.Staleness.IsIndexStale(index.IndexId, query.Cutoff, query.CutoffEtag);

				if (stale == false && query.Cutoff == null && query.CutoffEtag == null)
				{
					var indexInstance = database.IndexStorage.GetIndexInstance(indexName);
					stale = stale || (indexInstance != null && indexInstance.IsMapIndexingInProgress);
				}

				if (stale &&
					actions.Staleness.IsIndexStaleByTask(index.IndexId, query.Cutoff) == false &&
					actions.Staleness.IsReduceStale(index.IndexId) == false)
				{
					var forEntityNames = viewGenerator.ForEntityNames.ToList();
					var lastIndexedEtag = actions.Indexing.GetIndexStats(index.IndexId).LastIndexedEtag;

					if (database.LastCollectionEtags.HasEtagGreaterThan(forEntityNames, lastIndexedEtag) == false)
						stale = false;
				}

				indexTimestamp = actions.Staleness.IndexLastUpdatedAt(index.IndexId);
				var indexFailureInformation = actions.Indexing.GetFailureRate(index.IndexId);
				if (indexFailureInformation.IsInvalidIndex)
				{
					throw new IndexDisabledException(indexFailureInformation);
				}
				docRetriever = new DocumentRetriever(database.Configuration, actions, database.ReadTriggers, database.InFlightTransactionalState, query.TransformerParameters, idsToLoad);
				var fieldsToFetch = new FieldsToFetch(query,
					viewGenerator.ReduceDefinition == null
						? Constants.DocumentIdFieldName
						: Constants.ReduceKeyFieldName);
				Func<IndexQueryResult, bool> shouldIncludeInResults =
					result => docRetriever.ShouldIncludeResultInQuery(result, index, fieldsToFetch, ShouldSkipDuplicateChecking);
				var indexQueryResults = database.IndexStorage.Query(indexName, query, shouldIncludeInResults, fieldsToFetch, database.IndexQueryTriggers, cancellationToken);
				indexQueryResults = new ActiveEnumerable<IndexQueryResult>(indexQueryResults);

				if (query.ShowTimings)
					indexQueryResults = new TimedEnumerable<IndexQueryResult>(indexQueryResults, timeInMilliseconds => executionTimes[QueryTimings.Lucene] = timeInMilliseconds);

				var docs = from queryResult in indexQueryResults
						   let doc = docRetriever.RetrieveDocumentForQuery(queryResult, index, fieldsToFetch, ShouldSkipDuplicateChecking)
						   where doc != null
						   let _ = nonAuthoritativeInformation |= (doc.NonAuthoritativeInformation ?? false)
						   let __ = tryRecordHighlightingAndScoreExplanation(queryResult)
						   select doc;

				transformerErrors = new List<string>();
				results = database
					.Queries
					.GetQueryResults(query, viewGenerator, docRetriever, docs, transformerErrors,
						timeInMilliseconds => executionTimes[QueryTimings.LoadDocuments] = timeInMilliseconds,
						timeInMilliseconds => executionTimes[QueryTimings.TransformResults] = timeInMilliseconds,
						query.ShowTimings, cancellationToken);

				Header = new QueryHeaderInformation
				{
					Index = indexName,
					IsStale = stale,
					ResultEtag = resultEtag,
					IndexTimestamp = indexTimestamp.Item1,
					IndexEtag = indexTimestamp.Item2,
					TotalResults = query.TotalSize.Value
				};
			}
Exemple #4
0
		private IEnumerable<Tuple<IndexToWorkOn, IndexingBatch>> FilterIndexes(IList<IndexToWorkOn> indexesToWorkOn, JsonDocument[] jsonDocs)
		{
			var last = jsonDocs.Last();

			Debug.Assert(last.Etag != null);
			Debug.Assert(last.LastModified != null);

			var lastEtag = last.Etag.Value;
			var lastModified = last.LastModified.Value;

			var lastIndexedEtag = new ComparableByteArray(lastEtag.ToByteArray());

			var documentRetriever = new DocumentRetriever(null, context.ReadTriggers);

			var filteredDocs =
				BackgroundTaskExecuter.Instance.Apply(jsonDocs, doc =>
				{
					doc = documentRetriever.ExecuteReadTriggers(doc, null, ReadOperation.Index);
					return doc == null ? null : new {Doc = doc, Json = JsonToExpando.Convert(doc.ToJson())};
				});

			log.Debug("After read triggers executed, {0} documents remained", filteredDocs.Count);

			var results = new Tuple<IndexToWorkOn, IndexingBatch>[indexesToWorkOn.Count];
			var actions = new Action<IStorageActionsAccessor>[indexesToWorkOn.Count];

			BackgroundTaskExecuter.Instance.ExecuteAll(context.Configuration, scheduler, indexesToWorkOn, (indexToWorkOn, i) =>
			{
				var indexLastInedexEtag = new ComparableByteArray(indexToWorkOn.LastIndexedEtag.ToByteArray());
				if (indexLastInedexEtag.CompareTo(lastIndexedEtag) >= 0)
					return;

				var indexName = indexToWorkOn.IndexName;
				var viewGenerator = context.IndexDefinitionStorage.GetViewGenerator(indexName);
				if (viewGenerator == null)
					return; // probably deleted

				var batch = new IndexingBatch();

				foreach (var item in filteredDocs)
				{
					// did we already indexed this document in this index?
					if (indexLastInedexEtag.CompareTo(new ComparableByteArray(item.Doc.Etag.Value.ToByteArray())) >= 0)
						continue;


					// is the Raven-Entity-Name a match for the things the index executes on?
					if (viewGenerator.ForEntityNames.Count != 0 &&
					    viewGenerator.ForEntityNames.Contains(item.Doc.Metadata.Value<string>(Constants.RavenEntityName)) == false)
					{
						continue;
					}

					batch.Add(item.Doc, item.Json);

					if (batch.DateTime == null)
						batch.DateTime = item.Doc.LastModified;
					else
						batch.DateTime = batch.DateTime > item.Doc.LastModified
						                 	? item.Doc.LastModified
						                 	: batch.DateTime;
				}

				if (batch.Docs.Count == 0)
				{
					log.Debug("All documents have been filtered for {0}, no indexing will be performed, updating to {1}, {2}", indexName,
						lastEtag, lastModified);
					// we use it this way to batch all the updates together
					actions[i] = accessor => accessor.Indexing.UpdateLastIndexed(indexName, lastEtag, lastModified);
					return;
				}
				log.Debug("Going to index {0} documents in {1}", batch.Ids.Count, indexToWorkOn);
				results[i] = Tuple.Create(indexToWorkOn, batch);

			});

			transactionalStorage.Batch(actionsAccessor =>
			{
				foreach (var action in actions)
				{
					if (action != null)
						action(actionsAccessor);
				}
			});

			return results.Where(x => x != null);
		}
Exemple #5
0
        private void IndexDocuments(IStorageActionsAccessor actions, string index, JsonDocument[] jsonDocs)
        {
            var viewGenerator = context.IndexDefinitionStorage.GetViewGenerator(index);
            if (viewGenerator == null)
                return; // index was deleted, probably

            var dateTime = jsonDocs.Min(x => x.LastModified) ?? DateTime.MinValue;

            var documentRetriever = new DocumentRetriever(null, context.ReadTriggers);
            try
            {
                log.DebugFormat("Indexing {0} documents for index: {1}", jsonDocs.Length, index);
                context.IndexStorage.Index(index, viewGenerator,
                    jsonDocs
                    .Select(doc => documentRetriever
                        .ExecuteReadTriggers(doc, null, ReadOperation.Index))
                    .Where(doc => doc != null)
                    .Select(x => JsonToExpando.Convert(x.ToJson())), context, actions, dateTime);
            }
            catch (Exception e)
            {
                if (actions.IsWriteConflict(e))
                    return;
                log.WarnFormat(e, "Failed to index documents for index: {0}", index);
            }
        }
Exemple #6
0
        public void GetDocuments(int start, int pageSize, Etag etag, CancellationToken token, Action<RavenJObject> addDocument)
        {
            TransactionalStorage.Batch(actions =>
            {
                bool returnedDocs = false;
                while (true)
                {
                    var documents = etag == null
                                        ? actions.Documents.GetDocumentsByReverseUpdateOrder(start, pageSize)
                                        : actions.Documents.GetDocumentsAfter(etag, pageSize, WorkContext.CancellationToken);
                    var documentRetriever = new DocumentRetriever(actions, Database.ReadTriggers, Database.InFlightTransactionalState);
                    int docCount = 0;
                    foreach (var doc in documents)
                    {
                        docCount++;
                        token.ThrowIfCancellationRequested();
                        if (etag != null)
                            etag = doc.Etag;
                        DocumentRetriever.EnsureIdInMetadata(doc);
                        var nonAuthoritativeInformationBehavior = Database.InFlightTransactionalState.GetNonAuthoritativeInformationBehavior<JsonDocument>(null, doc.Key);
                        var document = nonAuthoritativeInformationBehavior == null ? doc : nonAuthoritativeInformationBehavior(doc);
                        document = documentRetriever
                            .ExecuteReadTriggers(document, null, ReadOperation.Load);
                        if (document == null)
                            continue;

                        addDocument(document.ToJson());
                        returnedDocs = true;
                    }
                    if (returnedDocs || docCount == 0)
                        break;
                    start += docCount;
                }
            });
        }
Exemple #7
0
        public JsonDocument GetWithTransformer(string key, string transformer, TransactionInformation transactionInformation, Dictionary<string, RavenJToken> transformerParameters, out HashSet<string> itemsToInclude)
        {
            JsonDocument result = null;
            DocumentRetriever docRetriever = null;
            TransactionalStorage.Batch(
            actions =>
            {
                docRetriever = new DocumentRetriever(actions, Database.ReadTriggers, Database.InFlightTransactionalState, transformerParameters);
                using (new CurrentTransformationScope(Database, docRetriever))
                {
                    var document = Get(key, transactionInformation);
                    if (document == null)
                        return;

                    if (document.Metadata.ContainsKey("Raven-Read-Veto"))
                    {
                        result = document;
                        return;
                    }

                    var storedTransformer = IndexDefinitionStorage.GetTransformer(transformer);
                    if (storedTransformer == null)
                        throw new InvalidOperationException("No transformer with the name: " + transformer);

                    var transformed = storedTransformer.TransformResultsDefinition(new[] { new DynamicJsonObject(document.ToJson()) })
                                     .Select(x => JsonExtensions.ToJObject(x))
                                     .ToArray();
                   
                    if (transformed.Length == 0)
                        return;

                    result = new JsonDocument
                    {
                        Etag = document.Etag.HashWith(storedTransformer.GetHashCodeBytes()).HashWith(docRetriever.Etag),
                        NonAuthoritativeInformation = document.NonAuthoritativeInformation,
                        LastModified = document.LastModified,
                        DataAsJson = new RavenJObject { { "$values", new RavenJArray(transformed) } },
                    };
                }
            });
            itemsToInclude = docRetriever.ItemsToInclude;
            return result;
        }
	    public CurrentTransformationScope(DocumentRetriever documentRetriever)
		{
			current = documentRetriever;
		}
Exemple #9
0
        public void GetDocumentsWithIdStartingWith(string idPrefix, string matches, string exclude, int start, int pageSize,
                                                   CancellationToken token, ref int nextStart, Action<RavenJObject> addDoc,
                                                   string transformer = null, Dictionary<string, RavenJToken> transformerParameters = null,
												   string skipAfter = null)
        {
            if (idPrefix == null)
                throw new ArgumentNullException("idPrefix");
            idPrefix = idPrefix.Trim();

            var canPerformRapidPagination = nextStart > 0 && start == nextStart;
            var actualStart = canPerformRapidPagination ? start : 0;
            var addedDocs = 0;
            var matchedDocs = 0;

            TransactionalStorage.Batch(
                actions =>
                {
                    var docsToSkip = canPerformRapidPagination ? 0 : start;
                    int docCount;

                    AbstractTransformer storedTransformer = null;
                    if (transformer != null)
                    {
                        storedTransformer = IndexDefinitionStorage.GetTransformer(transformer);
                        if (storedTransformer == null)
                            throw new InvalidOperationException("No transformer with the name: " + transformer);
                    }

                    do
                    {
                        docCount = 0;
						var docs = actions.Documents.GetDocumentsWithIdStartingWith(idPrefix, actualStart, pageSize, string.IsNullOrEmpty(skipAfter) ? null : skipAfter);
                        var documentRetriever = new DocumentRetriever(actions, Database.ReadTriggers, Database.InFlightTransactionalState, transformerParameters);

                        foreach (var doc in docs)
                        {
                            token.ThrowIfCancellationRequested();
                            docCount++;
                            var keyTest = doc.Key.Substring(idPrefix.Length);

                            if (!WildcardMatcher.Matches(matches, keyTest) || WildcardMatcher.MatchesExclusion(exclude, keyTest))
                                continue;

                            DocumentRetriever.EnsureIdInMetadata(doc);
                            var nonAuthoritativeInformationBehavior = Database.InFlightTransactionalState.GetNonAuthoritativeInformationBehavior<JsonDocument>(null, doc.Key);

                            var document = nonAuthoritativeInformationBehavior != null ? nonAuthoritativeInformationBehavior(doc) : doc;
                            document = documentRetriever.ExecuteReadTriggers(document, null, ReadOperation.Load);
                            if (document == null)
                                continue;

                            matchedDocs++;

                            if (matchedDocs <= docsToSkip)
                                continue;

                            token.ThrowIfCancellationRequested();

                            if (storedTransformer != null)
                            {
                                using (new CurrentTransformationScope(Database, documentRetriever))
                                {
                                    var transformed =
                                        storedTransformer.TransformResultsDefinition(new[] { new DynamicJsonObject(document.ToJson()) })
                                                         .Select(x => JsonExtensions.ToJObject(x))
                                                         .ToArray();

                                    if (transformed.Length == 0)
                                    {
                                        throw new InvalidOperationException("The transform results function failed on a document: " + document.Key);
                                    }

                                    var transformedJsonDocument = new JsonDocument
                                    {
                                        Etag = document.Etag.HashWith(storedTransformer.GetHashCodeBytes()).HashWith(documentRetriever.Etag),
                                        NonAuthoritativeInformation = document.NonAuthoritativeInformation,
                                        LastModified = document.LastModified,
                                        DataAsJson = new RavenJObject { { "$values", new RavenJArray(transformed) } },
                                    };

                                    addDoc(transformedJsonDocument.ToJson());
                                }

                            }
                            else
                            {
                                addDoc(document.ToJson());
                            }

                            addedDocs++;

                            if (addedDocs >= pageSize)
                                break;
                        }

                        actualStart += pageSize;
                    }
                    while (docCount > 0 && addedDocs < pageSize && actualStart > 0 && actualStart < int.MaxValue);
                });

            if (addedDocs != pageSize)
                nextStart = start; // will mark as last page
            else if (canPerformRapidPagination)
                nextStart = start + matchedDocs;
            else
                nextStart = actualStart;
        }
Exemple #10
0
        public Etag GetDocumentsWithIdStartingWith(string idPrefix, int pageSize, Etag etag, CancellationToken token, Func<JsonDocument, bool> addDocument)
        {
            Etag lastDocumentReadEtag = null;

            TransactionalStorage.Batch(actions =>
            {
                bool returnedDocs = false;
                while (true)
                {
                    var documents = actions.Documents.GetDocumentsAfterWithIdStartingWith(etag, idPrefix, pageSize, token, timeout: TimeSpan.FromSeconds(2), lastProcessedDocument: x => lastDocumentReadEtag = x );
                    var documentRetriever = new DocumentRetriever(Database.Configuration, actions, Database.ReadTriggers);
                    
                    int docCount = 0;
                    foreach (var doc in documents)
                    {
                        docCount++;                        
                        token.ThrowIfCancellationRequested();
                        
                        etag = doc.Etag;
                        
                        JsonDocument.EnsureIdInMetadata(doc);
                        
                        var nonAuthoritativeInformationBehavior = actions.InFlightStateSnapshot.GetNonAuthoritativeInformationBehavior<JsonDocument>(null, doc.Key);
                        var document = nonAuthoritativeInformationBehavior == null ? doc : nonAuthoritativeInformationBehavior(doc);
                       
                        document = documentRetriever.ExecuteReadTriggers(document, null, ReadOperation.Load);
                        if (document == null)
                            continue;

                        returnedDocs = true;
                        Database.WorkContext.UpdateFoundWork();

                        bool canContinue = addDocument(document);                                                                          
                        if (!canContinue)
                            break;
                    }

                    if (returnedDocs)
                        break;

                    // No document was found that matches the requested criteria
                    if ( docCount == 0 )
                    {
                        // If we had a failure happen, we update the etag as we don't need to process those documents again (no matches there anyways).
                        if (lastDocumentReadEtag != null)
                            etag = lastDocumentReadEtag;

                        break;
                    }
                }
            });

            return etag;
        }
Exemple #11
0
        public Etag GetDocuments(int start, int pageSize, Etag etag, CancellationToken token,
            Func<JsonDocument, bool> addDocument, long? maxSize = null, TimeSpan? timeout = null)
        {
            Etag lastDocumentReadEtag = null;

            using (DocumentCacher.SkipSetDocumentsInDocumentCache())
                TransactionalStorage.Batch(actions =>
                {
                    bool returnedDocs = false;
                    while (true)
                    {
                        var documents = etag == null
                            ? actions.Documents.GetDocumentsByReverseUpdateOrder(start, pageSize)
                            : actions.Documents.GetDocumentsAfter(etag, pageSize, token, maxSize: maxSize, timeout: timeout);

                        var documentRetriever = new DocumentRetriever(Database.Configuration, actions, Database.ReadTriggers);
                        var docCount = 0;
                        foreach (var doc in documents)
                        {
                            docCount++;

                            token.ThrowIfCancellationRequested();

                            if (etag != null)
                                etag = doc.Etag;

                            JsonDocument.EnsureIdInMetadata(doc);

                            var nonAuthoritativeInformationBehavior = actions.InFlightStateSnapshot.GetNonAuthoritativeInformationBehavior<JsonDocument>(null, doc.Key);
                            var document = nonAuthoritativeInformationBehavior == null ? doc : nonAuthoritativeInformationBehavior(doc);

                            document = documentRetriever.ExecuteReadTriggers(document, null, ReadOperation.Load);
                            if (document == null)
                                continue;

                            returnedDocs = true;
                            Database.WorkContext.UpdateFoundWork();

                            bool canContinue = addDocument(document);
                            if (!canContinue)
                                break;

                            lastDocumentReadEtag = etag;
                        }

                        if (returnedDocs || docCount == 0)
                            break;

                        // No document was found that matches the requested criteria
                        // If we had a failure happen, we update the etag as we don't need to process those documents again (no matches there anyways).
                        if (lastDocumentReadEtag != null)
                            etag = lastDocumentReadEtag;

                        start += docCount;
                    }
                });

            return lastDocumentReadEtag;
        }
		public MoreLikeThisQueryResult ExecuteMoreLikeThisQuery(MoreLikeThisQuery query, TransactionInformation transactionInformation, int pageSize = 25)
		{
			if (query == null) throw new ArgumentNullException("query");

			var index = database.IndexStorage.GetIndexInstance(query.IndexName);
			if (index == null)
				throw new InvalidOperationException("The index " + query.IndexName + " cannot be found");

			if (string.IsNullOrEmpty(query.DocumentId) && query.MapGroupFields.Count == 0)
				throw new InvalidOperationException("The document id or map group fields are mandatory");

			IndexSearcher searcher;
			using (database.IndexStorage.GetCurrentIndexSearcher(index.indexId, out searcher))
			{
				var documentQuery = new BooleanQuery();

				if (string.IsNullOrEmpty(query.DocumentId) == false)
				{
					documentQuery.Add(new TermQuery(new Term(Constants.DocumentIdFieldName, query.DocumentId.ToLowerInvariant())), Occur.MUST);
				}

				foreach (string key in query.MapGroupFields.Keys)
				{
					documentQuery.Add(new TermQuery(new Term(key, query.MapGroupFields[key])), Occur.MUST);
				}

				var td = searcher.Search(documentQuery, 1);

				// get the current Lucene docid for the given RavenDB doc ID
				if (td.ScoreDocs.Length == 0)
					throw new InvalidOperationException("Document " + query.DocumentId + " could not be found");

				var ir = searcher.IndexReader;
				var mlt = new RavenMoreLikeThis(ir);

				AssignParameters(mlt, query);

				if (string.IsNullOrWhiteSpace(query.StopWordsDocumentId) == false)
				{
					var stopWordsDoc = database.Documents.Get(query.StopWordsDocumentId, null);
					if (stopWordsDoc == null)
						throw new InvalidOperationException("Stop words document " + query.StopWordsDocumentId + " could not be found");

					var stopWordsSetup = stopWordsDoc.DataAsJson.JsonDeserialization<StopWordsSetup>();
					if (stopWordsSetup.StopWords != null)
					{
						var stopWords = stopWordsSetup.StopWords;
						var ht = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
						foreach (var stopWord in stopWords)
						{
							ht.Add(stopWord);
						}
						mlt.SetStopWords(ht);
					}
				}

				var fieldNames = query.Fields ?? GetFieldNames(ir);
				mlt.SetFieldNames(fieldNames);

				var toDispose = new List<Action>();
				RavenPerFieldAnalyzerWrapper perFieldAnalyzerWrapper = null;
				try
				{
					perFieldAnalyzerWrapper = index.CreateAnalyzer(new LowerCaseKeywordAnalyzer(), toDispose, true);
					mlt.Analyzer = perFieldAnalyzerWrapper;

					var mltQuery = mlt.Like(td.ScoreDocs[0].Doc);
					var tsdc = TopScoreDocCollector.Create(pageSize, true);


				    if (string.IsNullOrWhiteSpace(query.AdditionalQuery) == false)
				    {
				        var additionalQuery = QueryBuilder.BuildQuery(query.AdditionalQuery, perFieldAnalyzerWrapper);
				        mltQuery = new BooleanQuery
				        {
                            {mltQuery, Occur.MUST},
				            {additionalQuery, Occur.MUST}, 
				        };
				    }

				    searcher.Search(mltQuery, tsdc);
					var hits = tsdc.TopDocs().ScoreDocs;
					var jsonDocuments = GetJsonDocuments(query, searcher, index, query.IndexName, hits, td.ScoreDocs[0].Doc);

					var result = new MultiLoadResult();

					var includedEtags = new List<byte>(jsonDocuments.SelectMany(x => x.Etag.ToByteArray()));
					includedEtags.AddRange(database.Indexes.GetIndexEtag(query.IndexName, null).ToByteArray());
					var loadedIds = new HashSet<string>(jsonDocuments.Select(x => x.Key));
					var addIncludesCommand = new AddIncludesCommand(database, transactionInformation, (etag, includedDoc) =>
					{
						includedEtags.AddRange(etag.ToByteArray());
						result.Includes.Add(includedDoc);
					}, query.Includes ?? new string[0], loadedIds);

					idsToLoad = new HashSet<string>();

					database.TransactionalStorage.Batch(actions =>
					{
						documentRetriever = new DocumentRetriever(database.Configuration, actions, database.ReadTriggers, database.InFlightTransactionalState, query.TransformerParameters, idsToLoad);

						using (new CurrentTransformationScope(database, documentRetriever))
						{
							foreach (var document in ProcessResults(query, jsonDocuments, database.WorkContext.CancellationToken))
							{
								result.Results.Add(document);
								addIncludesCommand.Execute(document);
							}
						}
					});

					addIncludesCommand.AlsoInclude(idsToLoad);

				    var computeHash = Encryptor.Current.Hash.Compute16(includedEtags.ToArray());
                    Etag computedEtag = Etag.Parse(computeHash);

					return new MoreLikeThisQueryResult
					{
						Etag = computedEtag,
						Result = result,
					};
				}
				finally
				{
					if (perFieldAnalyzerWrapper != null)
						perFieldAnalyzerWrapper.Close();
					foreach (var action in toDispose)
					{
						action();
					}
				}
			}
		}
		public void CanExecuteTheTransformResultFunction()
		{
			var answersIndex = new Answers_ByAnswerEntity2 { Conventions = new DocumentConvention() };
			IndexDefinition indexDefinition = answersIndex.CreateIndexDefinition();
			var dynamicViewCompiler = new DynamicViewCompiler("test", indexDefinition, ".");
			AbstractViewGenerator abstractViewGenerator = dynamicViewCompiler.GenerateInstance();
			using (var documentStore = NewDocumentStore())
			{

				Guid questionId = Guid.NewGuid();
				Guid answerId = Guid.NewGuid();

				using (IDocumentSession session = documentStore.OpenSession())
				{
					var user = new User { Id = @"user\222", DisplayName = "John Doe" };
					session.Store(user);

					var question = new Question2
					{
						Id = questionId,
						Title = "How to do this in RavenDb?",
						Content = "I'm trying to find how to model documents for better DDD support.",
						UserId = @"user\222"
					};
					session.Store(question);


					var answer = new AnswerEntity2
					{
						Id = answerId,
						Question = question,
						Content = "This is doable",
						UserId = user.Id
					};
					answer.Votes = new[]
					{
						new AnswerVoteEntity2
						{
							Id = Guid.NewGuid(),
							QuestionId = questionId,
							Answer = answer,
							Delta = 2
						}
					};


					session.Store(new Answer2
					{
						Id = answerId,
						UserId = user.Id,
						QuestionId = question.Id,
						Content = "This is doable",
						Votes = new[]
						{
							new AnswerVote2
							{
								Id = Guid.NewGuid(),
								QuestionId = questionId,
								AnswerId = answerId,
								Delta = 2
							}
						}
					});

					session.SaveChanges();
				}

				documentStore.DocumentDatabase.TransactionalStorage.Batch(accessor =>
				{
					var documentRetriever = new DocumentRetriever(accessor, new OrderedPartCollection<AbstractReadTrigger>());
					var dynamicJsonObjects = new[] { new DynamicJsonObject(accessor.Documents.DocumentByKey("answer2s/" + answerId.ToString(), null).ToJson()), };
					var transformResultsDefinition = abstractViewGenerator.TransformResultsDefinition(documentRetriever,
																									  dynamicJsonObjects
						);

					transformResultsDefinition.ToArray();
				});



			}
		}
Exemple #14
0
        public Etag GetDocuments(int start, int pageSize, Etag etag, CancellationToken token, Func<JsonDocument, bool> addDocument)
        {
            Etag lastDocumentReadEtag = null;

            TransactionalStorage.Batch(actions =>
            {
                bool returnedDocs = false;
                while (true)
                {
                    var documents = etag == null
                                        ? actions.Documents.GetDocumentsByReverseUpdateOrder(start, pageSize)
                                        : actions.Documents.GetDocumentsAfter(etag, pageSize, token);

                    var documentRetriever = new DocumentRetriever(Database.Configuration, actions, Database.ReadTriggers, Database.InFlightTransactionalState);
                    int docCount = 0;
                    foreach (var doc in documents)
                    {
                        docCount++;

                        token.ThrowIfCancellationRequested();

                        if (etag != null)
                            etag = doc.Etag;

                        JsonDocument.EnsureIdInMetadata(doc);

                        var nonAuthoritativeInformationBehavior = Database.InFlightTransactionalState.GetNonAuthoritativeInformationBehavior<JsonDocument>(null, doc.Key);
                        var document = nonAuthoritativeInformationBehavior == null ? doc : nonAuthoritativeInformationBehavior(doc);
                        
                        document = documentRetriever.ExecuteReadTriggers(document, null, ReadOperation.Load);
                        if (document == null)
                            continue;
                        
                        returnedDocs = true;
                        Database.WorkContext.UpdateFoundWork();
                        
                        bool canContinue = addDocument(document);
                        if (!canContinue)
                            break;

                        lastDocumentReadEtag = etag;
                    }

                    if (returnedDocs || docCount == 0)
                        break;

                    start += docCount;
                }
            });

            return lastDocumentReadEtag;
        }
Exemple #15
0
        private IEnumerable<RavenJObject> GetQueryResults(IndexQuery query,
            AbstractViewGenerator viewGenerator,
            DocumentRetriever docRetriever,
            IEnumerable<JsonDocument> results,
            List<string> transformerErrors,
            CancellationToken token)
        {
            if (query.PageSize <= 0) // maybe they just want the stats? 
            {
                return Enumerable.Empty<RavenJObject>();
            }

            IndexingFunc transformFunc = null;

            // Check an explicitly declared one first
            if (string.IsNullOrEmpty(query.ResultsTransformer) == false)
            {
                var transformGenerator = IndexDefinitionStorage.GetTransformer(query.ResultsTransformer);

                if (transformGenerator != null && transformGenerator.TransformResultsDefinition != null)
                    transformFunc = transformGenerator.TransformResultsDefinition;
                else
                    throw new InvalidOperationException("The transformer " + query.ResultsTransformer + " was not found");
            }
            else if (query.SkipTransformResults == false && viewGenerator.TransformResultsDefinition != null)
            {
                transformFunc = source => viewGenerator.TransformResultsDefinition(docRetriever, source);
            }

            if (transformFunc == null)
                return results.Select(x => x.ToJson());

            var dynamicJsonObjects = results.Select(x => new DynamicLuceneOrParentDocumntObject(docRetriever, x.ToJson()));
            var robustEnumerator = new RobustEnumerator(token, 100)
            {
                OnError =
                    (exception, o) =>
                    transformerErrors.Add(string.Format("Doc '{0}', Error: {1}", Index.TryGetDocKey(o),
                                                        exception.Message))
            };
            return robustEnumerator.RobustEnumeration(
                dynamicJsonObjects.Cast<object>().GetEnumerator(),
                transformFunc)
                .Select(JsonExtensions.ToJObject);
        }
		public void Dispose()
		{
			current = null;
		}
Exemple #17
0
		private IEnumerable<RavenJObject> GetQueryResults(IndexQuery query, AbstractViewGenerator viewGenerator, DocumentRetriever docRetriever, IEnumerable<JsonDocument> results, List<string> transformerErrors, Action<double> loadingDocumentsFinish, Action<double> transformerFinish, bool showTimings, CancellationToken token)
		{
			if (query.PageSize <= 0) // maybe they just want the stats? 
			{
				return Enumerable.Empty<RavenJObject>();
			}

			IndexingFunc transformFunc = null;

			// Check an explicitly declared one first
			if (string.IsNullOrEmpty(query.ResultsTransformer) == false)
			{
				var transformGenerator = IndexDefinitionStorage.GetTransformer(query.ResultsTransformer);

				if (transformGenerator != null && transformGenerator.TransformResultsDefinition != null)
					transformFunc = transformGenerator.TransformResultsDefinition;
				else
					throw new InvalidOperationException("The transformer " + query.ResultsTransformer + " was not found");
			}

			if (transformFunc == null)
			{
				var resultsWithoutTransformer = results.Select(x =>
				{
					var ravenJObject = x.ToJson();
					if (query.IsDistinct)
					{
						ravenJObject[Constants.DocumentIdFieldName] = x.Key;
					}
					return ravenJObject;
				});
				return showTimings ? new TimedEnumerable<RavenJObject>(resultsWithoutTransformer, loadingDocumentsFinish) : resultsWithoutTransformer;
			}

			var dynamicJsonObjects = results.Select(x =>
			{
				var ravenJObject = x.ToJson();
				if (query.IsDistinct)
				{
					ravenJObject[Constants.DocumentIdFieldName] = x.Key;
				}
				return new DynamicLuceneOrParentDocumntObject(docRetriever, ravenJObject);
			});
			var robustEnumerator = new RobustEnumerator(token, 100)
			{
				OnError =
					(exception, o) =>
					transformerErrors.Add(string.Format("Doc '{0}', Error: {1}", Index.TryGetDocKey(o),
														exception.Message))
			};

			var resultsWithTransformer = robustEnumerator
				.RobustEnumeration(dynamicJsonObjects.Cast<object>().GetEnumerator(), transformFunc)
				.Select(JsonExtensions.ToJObject);

			return showTimings ? new TimedEnumerable<RavenJObject>(resultsWithTransformer, transformerFinish) : resultsWithTransformer;
		}
 public DynamicLuceneOrParentDocumntObject(DocumentRetriever retriever,RavenJObject inner) : base(inner)
 {
     this.retriever = retriever;
 }
Exemple #19
0
		private IEnumerable<IndexingBatchForIndex> FilterIndexes(IList<IndexToWorkOn> indexesToWorkOn, List<JsonDocument> jsonDocs, Etag highestETagInBatch)
		{
			var last = jsonDocs.Last();

			Debug.Assert(last.Etag != null);
			Debug.Assert(last.LastModified != null);

			var lastEtag = last.Etag;
			var lastModified = last.LastModified.Value;

			var documentRetriever = new DocumentRetriever(null, context.ReadTriggers, context.Database.InFlightTransactionalState);

			var filteredDocs =
				BackgroundTaskExecuter.Instance.Apply(context, jsonDocs, doc =>
				{
					var filteredDoc = documentRetriever.ExecuteReadTriggers(doc, null, ReadOperation.Index);
					return filteredDoc == null ? new
					{
						Doc = doc,
						Json = (object)new FilteredDocument(doc)
					} : new
					{
						Doc = filteredDoc,
						Json = JsonToExpando.Convert(doc.ToJson())
					};
				});

			Log.Debug("After read triggers executed, {0} documents remained", filteredDocs.Count);

			var results = new IndexingBatchForIndex[indexesToWorkOn.Count];
			var actions = new Action<IStorageActionsAccessor>[indexesToWorkOn.Count];

			BackgroundTaskExecuter.Instance.ExecuteAll(context, indexesToWorkOn, (indexToWorkOn, i) =>
			{
				var indexName = indexToWorkOn.IndexName;
				var viewGenerator = context.IndexDefinitionStorage.GetViewGenerator(indexName);
				if (viewGenerator == null)
					return; // probably deleted

				var batch = new IndexingBatch(highestETagInBatch);

				foreach (var item in filteredDocs)
				{
					if (prefetchingBehavior.FilterDocuments(item.Doc) == false)
						continue;

					// did we already indexed this document in this index?
					var etag = item.Doc.Etag;
					if (etag == null)
						continue;

					// is the Raven-Entity-Name a match for the things the index executes on?
					if (viewGenerator.ForEntityNames.Count != 0 &&
						viewGenerator.ForEntityNames.Contains(item.Doc.Metadata.Value<string>(Constants.RavenEntityName)) == false)
					{
						continue;
					}

					batch.Add(item.Doc, item.Json, prefetchingBehavior.ShouldSkipDeleteFromIndex(item.Doc));

					if (batch.DateTime == null)
						batch.DateTime = item.Doc.LastModified;
					else
						batch.DateTime = batch.DateTime > item.Doc.LastModified
											 ? item.Doc.LastModified
											 : batch.DateTime;
				}

				if (batch.Docs.Count == 0)
				{
					Log.Debug("All documents have been filtered for {0}, no indexing will be performed, updating to {1}, {2}", indexName,
							  lastEtag, lastModified);
					// we use it this way to batch all the updates together
					actions[i] = accessor => accessor.Indexing.UpdateLastIndexed(indexName, lastEtag, lastModified);
					return;
				}
				if (Log.IsDebugEnabled)
				{
					Log.Debug("Going to index {0} documents in {1}: ({2})", batch.Ids.Count, indexToWorkOn, string.Join(", ", batch.Ids));
				}
				results[i] = new IndexingBatchForIndex
				{
					Batch = batch,
					IndexName = indexToWorkOn.IndexName,
					Index = indexToWorkOn.Index,
					LastIndexedEtag = indexToWorkOn.LastIndexedEtag
				};

			});

			transactionalStorage.Batch(actionsAccessor =>
			{
				foreach (var action in actions)
				{
					if (action != null)
						action(actionsAccessor);
				}
			});

			return results.Where(x => x != null);
		}
        public RemoteQueryResults Query(LinearQuery query)
        {
            var viewGenerator = queryCache.GetOrAdd(query.Query,
                                                    s =>
                                                    new DynamicViewCompiler("query", new IndexDefinition { Map = query.Query, },
                                                                            new AbstractDynamicCompilationExtension[0])
                                                    {
                                                        RequiresSelectNewAnonymousType = false
                                                    }.GenerateInstance());

            var results = new List<string>();
            var errors = new List<string>();
            int lastResult = 0;
            int finalResult = 0;
            remoteStorage.Batch(actions =>
            {
                var firstAndLastDocumentIds = actions.Documents.FirstAndLastDocumentIds();
                finalResult = firstAndLastDocumentIds.Item2;
                var start = Math.Max(firstAndLastDocumentIds.Item1, query.Start);
                var matchingDocs = actions.Documents.DocumentsById(start, firstAndLastDocumentIds.Item2);

                if (string.IsNullOrEmpty(viewGenerator.ForEntityName) == false) //optimization
                {
                    matchingDocs =
                        matchingDocs.Where(x => x.Item1.Metadata.Value<string>("Raven-Entity-Name") == viewGenerator.ForEntityName);
                }

                var documentRetriever = new DocumentRetriever(actions, new AbstractReadTrigger[0]);
                var docs = matchingDocs
                    .Select(x=>
                    {
                        documentRetriever.EnsureIdInMetadata(x.Item1);
                        return x;
                    })
                    .Select(x =>
                    {
                        lastResult = x.Item2;
                        return new DynamicJsonObject(x.Item1.ToJson());
                    });

                var robustEnumerator = new RobustEnumerator
                {
                    OnError =
                        (exception, o) =>
                        errors.Add(String.Format("Doc '{0}', Error: {1}", Index.TryGetDocKey(o),
                                                 exception.Message))
                };
                results.AddRange(
                    robustEnumerator.RobustEnumeration(docs, viewGenerator.MapDefinition)
                        .Take(query.PageSize)
                        .Select(result => JsonExtensions.ToJObject(result).ToString())
                    );
            });

            return new RemoteQueryResults
            {
                LastScannedResult = lastResult,
                TotalResults = finalResult,
                Errors = errors.ToArray(),
                QueryCacheSize = queryCache.Count,
                Results = results.ToArray()
            };
        }