예제 #1
0
		private async Task<HttpResponseMessage> GetQueriesResponse(bool isGet)
		{
			RavenJArray itemsToLoad;
		    if (isGet == false)
		    {
		        itemsToLoad = await ReadJsonArrayAsync();
                AddRequestTraceInfo(sb =>
                {
                    foreach (var item in itemsToLoad)
                    {
                        sb.Append("\t").Append(item).AppendLine();
                    }
                });
		    }
		    else
		    {
		        itemsToLoad = new RavenJArray(GetQueryStringValues("id").Cast<object>());
		    }

			var result = new MultiLoadResult();
			var loadedIds = new HashSet<string>();
            var includedIds = new HashSet<string>();
			var includes = GetQueryStringValues("include") ?? new string[0];
			var transformer = GetQueryStringValue("transformer") ?? GetQueryStringValue("resultTransformer");
			var queryInputs = ExtractQueryInputs();
			var transactionInformation = GetRequestTransaction();
			var includedEtags = new List<byte>();

		    if (string.IsNullOrEmpty(transformer) == false)
		    {
                var transformerDef = Database.IndexDefinitionStorage.GetTransformer(transformer);
		        if (transformerDef == null)
		            return GetMessageWithObject(new {Error = "No such transformer: " + transformer}, HttpStatusCode.BadRequest);
                includedEtags.AddRange(transformerDef.GetHashCodeBytes());

		    }

			Database.TransactionalStorage.Batch(actions =>
			{
				foreach (RavenJToken item in itemsToLoad)
				{
					var value = item.Value<string>();
					if (loadedIds.Add(value) == false)
						continue;
					var documentByKey = string.IsNullOrEmpty(transformer)
										? Database.Documents.Get(value, transactionInformation)
                                        : Database.Documents.GetWithTransformer(value, transformer, transactionInformation, queryInputs, out includedIds);
				    if (documentByKey == null)
				    {
                        if(ClientIsV3OrHigher)
                            result.Results.Add(null); 
                        continue;
				    }
					result.Results.Add(documentByKey.ToJson());

					if (documentByKey.Etag != null)
						includedEtags.AddRange(documentByKey.Etag.ToByteArray());

					includedEtags.Add((documentByKey.NonAuthoritativeInformation ?? false) ? (byte)0 : (byte)1);
				}

				var addIncludesCommand = new AddIncludesCommand(Database, transactionInformation, (etag, includedDoc) =>
				{
					includedEtags.AddRange(etag.ToByteArray());
					result.Includes.Add(includedDoc);
				}, includes, loadedIds);

				foreach (var item in result.Results.Where(item => item != null))
				{
					addIncludesCommand.Execute(item);
				}
			});


			foreach (var includedId in includedIds)
		    {
		        var doc = Database.Documents.Get(includedId, transactionInformation);
		        if (doc == null)
		        {
                    continue;
		        }
                includedEtags.AddRange(doc.Etag.ToByteArray());
		        result.Includes.Add(doc.ToJson());
		    }

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

			if (MatchEtag(computedEtag))
			{
				return GetEmptyMessage(HttpStatusCode.NotModified);
			}

			var msg = GetMessageWithObject(result);
			WriteETag(computedEtag, msg);

			AddRequestTraceInfo(sb => sb.Append("Results count: {0}, includes count: {1}", result.Results.Count, result.Includes.Count).AppendLine());

			return msg;
		}
예제 #2
0
		private HttpResponseMessage GetIndexQueryResult(string index, CancellationToken token)
		{
			Etag indexEtag;
			var msg = GetEmptyMessage();
			var queryResult = ExecuteQuery(index, out indexEtag, msg, token);

			if (queryResult == null)
				return msg;

			var includes = GetQueryStringValues("include") ?? new string[0];
			var loadedIds = new HashSet<string>(
				queryResult.Results
					.Where(x => x != null && x["@metadata"] != null)
					.Select(x => x["@metadata"].Value<string>("@id"))
					.Where(x => x != null)
				);
			var command = new AddIncludesCommand(Database, GetRequestTransaction(),
												 (etag, doc) => queryResult.Includes.Add(doc), includes, loadedIds);
			foreach (var result in queryResult.Results)
			{
				command.Execute(result);
			}
			command.AlsoInclude(queryResult.IdsToInclude);

			return GetMessageWithObject(queryResult, queryResult.NonAuthoritativeInformation ? HttpStatusCode.NonAuthoritativeInformation : HttpStatusCode.OK, indexEtag);
		}
예제 #3
0
		public MoreLikeThisQueryResult ExecuteMoreLikeThisQuery(MoreLikeThisQuery query, TransactionInformation transactionInformation, int pageSize = 25, string[] include = null)
		{
			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);
					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);
					}, include ?? new string[0], loadedIds);

					foreach (var jsonDocument in jsonDocuments)
					{
						result.Results.Add(jsonDocument.ToJson());
						addIncludesCommand.Execute(jsonDocument.DataAsJson);
					}

					Etag computedEtag;
					using (var md5 = MD5.Create())
					{
						var computeHash = md5.ComputeHash(includedEtags.ToArray());
						computedEtag = Etag.Parse(computeHash);
					}

					return new MoreLikeThisQueryResult
					{
						Etag = computedEtag,
						Result = result,
					};
				}
				finally
				{
					if (perFieldAnalyzerWrapper != null)
						perFieldAnalyzerWrapper.Close();
					foreach (var action in toDispose)
					{
						action();
					}
				}
			}
		}