private static Domain.Model.QueryResult GetNeuronResults(Guid?centralGuid, Guid?relativeGuid, string settingName, NeuronQuery neuronQuery, CancellationToken token = default(CancellationToken)) { Domain.Model.QueryResult result = null; using (var db = ArangoDatabase.CreateWithSetting(settingName)) { var queryResult = db.CreateStatement <Domain.Model.NeuronResult>( NeuronRepository.CreateQuery(centralGuid, relativeGuid, neuronQuery, out List <QueryParameter> queryParameters), queryParameters, options: new QueryOption() { FullCount = true } ); var neurons = queryResult.AsEnumerable().ToArray(); if (centralGuid.HasValue) { neurons.ToList().ForEach(nr => nr.Terminal = nr.Terminal.CloneExcludeSynapticPrefix()); } var fullCount = (int)queryResult.Statistics.Extra.Stats.FullCount; if ( neuronQuery.Page.Value != 1 && fullCount == NeuronRepository.CalculateOffset(neuronQuery.Page.Value, neuronQuery.PageSize.Value) && neurons.Length == 0 ) { throw new ArgumentOutOfRangeException("Specified/Default Page is invalid."); } result = new Domain.Model.QueryResult() { Count = fullCount, Neurons = neurons }; } return(result); }
private static string CreateQuery(Guid?centralGuid, Guid?relativeGuid, NeuronQuery neuronQuery, out List <QueryParameter> queryParameters) { queryParameters = new List <QueryParameter>(); var queryFiltersBuilder = new StringBuilder(); var queryStringBuilder = new StringBuilder(); Func <string, string> valueBuilder = s => $"%{s}%"; Func <string, List <string>, string, string> selector = (f, ls, s) => $"Upper(n.Tag) LIKE Upper(@{f + (ls.IndexOf(s) + 1)})"; // TagContains NeuronRepository.ExtractFilters(neuronQuery.TagContains, nameof(NeuronQuery.TagContains), valueBuilder, selector, queryParameters, queryFiltersBuilder, "&&"); // TagContainsNot NeuronRepository.ExtractFilters(neuronQuery.TagContainsNot, nameof(NeuronQuery.TagContainsNot), valueBuilder, selector, queryParameters, queryFiltersBuilder, "||", "NOT"); valueBuilder = s => $"Neuron/{s}"; selector = (f, ls, s) => $"n._id == @{f + (ls.IndexOf(s) + 1)}"; // IdEquals NeuronRepository.ExtractFilters(neuronQuery.Id, nameof(NeuronQuery.Id), valueBuilder, selector, queryParameters, queryFiltersBuilder, "||"); // IdEqualsNot NeuronRepository.ExtractFilters(neuronQuery.IdNot, nameof(NeuronQuery.IdNot), valueBuilder, selector, queryParameters, queryFiltersBuilder, "||", "NOT"); valueBuilder = s => s; selector = (f, ls, s) => $"n.RegionId == @{f + (ls.IndexOf(s) + 1)}"; // RegionIdEquals NeuronRepository.ExtractFilters(neuronQuery.RegionId, nameof(NeuronQuery.RegionId), valueBuilder, selector, queryParameters, queryFiltersBuilder, "||"); // RegionIdEqualsNot NeuronRepository.ExtractFilters(neuronQuery.RegionIdNot, nameof(NeuronQuery.RegionIdNot), valueBuilder, selector, queryParameters, queryFiltersBuilder, "||", "NOT"); var neuronAuthorRegion = @" LET neuronCreationAuthorTag = ( FOR neuronAuthorNeuron in Neuron FILTER neuronAuthorNeuron._id == CONCAT(""Neuron/"", n.CreationAuthorId) return neuronAuthorNeuron.Tag ) LET neuronLastModificationAuthorTag = ( FOR neuronAuthorNeuron in Neuron FILTER neuronAuthorNeuron._id == CONCAT(""Neuron/"", n.LastModificationAuthorId) return neuronAuthorNeuron.Tag ) LET neuronUnifiedLastModificationAuthorTag = ( FOR neuronAuthorNeuron in Neuron FILTER neuronAuthorNeuron._id == CONCAT(""Neuron/"", n.UnifiedLastModificationAuthorId) return neuronAuthorNeuron.Tag ) LET neuronRegionTag = ( FOR regionNeuron in Neuron FILTER regionNeuron._id == CONCAT(""Neuron/"", n.RegionId) return regionNeuron.Tag )"; var neuronAuthorRegionReturn = ", NeuronCreationAuthorTag: FIRST(neuronCreationAuthorTag), NeuronLastModificationAuthorTag: FIRST(neuronLastModificationAuthorTag), NeuronUnifiedLastModificationAuthorTag: FIRST(neuronUnifiedLastModificationAuthorTag), NeuronRegionTag: FIRST(neuronRegionTag)"; if (!centralGuid.HasValue) { // Neuron Active NeuronRepository.AddActiveFilter("n", neuronQuery.NeuronActiveValues.Value, queryFiltersBuilder); queryStringBuilder.Append($@" FOR n IN Neuron {queryFiltersBuilder} {neuronAuthorRegion} RETURN {{ Neuron: n, Terminal: {{}}{neuronAuthorRegionReturn} }}"); } else { // Terminal Active NeuronRepository.AddActiveFilter("t", neuronQuery.TerminalActiveValues.Value, queryFiltersBuilder); string letPre = string.Empty, inPre = string.Empty, filterPre = string.Empty; string activeSynapticTemplate = string.Empty; if (Helper.TryConvert(neuronQuery.NeuronActiveValues.Value, out bool active)) { activeSynapticTemplate = " && {0}.Active == " + active.ToString(); } if (neuronQuery.RelativeValues.Value.HasFlag(RelativeValues.Presynaptic)) { // get all presynaptic neurons of current terminal letPre = $@"LET presynaptics = ( FOR presynaptic IN Neuron FILTER presynaptic._id == t._from{string.Format(activeSynapticTemplate, "presynaptic")} return presynaptic )"; // where "to" is centralGuid inPre = $@"t._to == @{nameof(centralGuid)} && LENGTH(presynaptics) > 0 ? presynaptics :"; filterPre = $@"t._to == @{nameof(centralGuid)}"; if (relativeGuid.HasValue) { filterPre += $@" && t._from == @{nameof(relativeGuid)}"; } } string letPost = string.Empty, inPost = string.Empty, filterPost = string.Empty; if (neuronQuery.RelativeValues.Value.HasFlag(RelativeValues.Postsynaptic)) { // get postsynaptic neurons letPost = $@"LET postsynaptics = ( FOR postsynaptic IN Neuron FILTER postsynaptic._id == t._to{string.Format(activeSynapticTemplate, "postsynaptic")} return postsynaptic )"; inPost = $@"t._from == @{nameof(centralGuid)} && LENGTH(postsynaptics) > 0 ? postsynaptics :"; filterPost = $@"t._from == @{nameof(centralGuid)}"; if (relativeGuid.HasValue) { filterPost += $@" && t._to == @{nameof(relativeGuid)}"; } } queryStringBuilder.Append($@" FOR t in Terminal {letPost} {letPre} FOR n IN ( {inPost} {inPre} [ {{ }} ] ) LET terminalCreationAuthorTag = ( FOR terminalAuthorNeuron in Neuron FILTER terminalAuthorNeuron._id == CONCAT(""Neuron/"", t.CreationAuthorId) return terminalAuthorNeuron.Tag ) LET terminalLastModificationAuthorTag = ( FOR terminalAuthorNeuron in Neuron FILTER terminalAuthorNeuron._id == CONCAT(""Neuron/"", t.LastModificationAuthorId) return terminalAuthorNeuron.Tag ) {neuronAuthorRegion} FILTER {filterPost} {(!string.IsNullOrEmpty(filterPost) && !string.IsNullOrEmpty(filterPre) ? "||" : string.Empty)} {filterPre} {queryFiltersBuilder} RETURN {{ Neuron: n, Terminal: t, TerminalCreationAuthorTag: FIRST(terminalCreationAuthorTag), TerminalLastModificationAuthorTag: FIRST(terminalLastModificationAuthorTag){neuronAuthorRegionReturn}}}"); queryParameters.Add(new QueryParameter() { Name = nameof(centralGuid), Value = $"Neuron/{centralGuid.Value.ToString()}" }); if (relativeGuid.HasValue) { queryParameters.Add(new QueryParameter() { Name = nameof(relativeGuid), Value = $"Neuron/{relativeGuid.Value.ToString()}" }); } } var preSynapticParamCount = queryParameters.Count; // Postsynaptic NeuronRepository.ApplySynapticFilters(neuronQuery.Postsynaptic, nameof(NeuronQuery.Postsynaptic), queryParameters, queryStringBuilder); // PostsynapticNot NeuronRepository.ApplySynapticFilters(neuronQuery.PostsynapticNot, nameof(NeuronQuery.PostsynapticNot), queryParameters, queryStringBuilder, false); // Presynaptic NeuronRepository.ApplySynapticFilters(neuronQuery.Presynaptic, nameof(NeuronQuery.Presynaptic), queryParameters, queryStringBuilder); // PresynapticNot NeuronRepository.ApplySynapticFilters(neuronQuery.PresynapticNot, nameof(NeuronQuery.PresynapticNot), queryParameters, queryStringBuilder, false); // Sort and Limit var lastReturnIndex = queryStringBuilder.ToString().ToUpper().LastIndexOf("RETURN"); queryStringBuilder.Remove(lastReturnIndex, 6); // were synaptic filters applied? bool synapticFiltersApplied = preSynapticParamCount < queryParameters.Count; string sortFieldName = synapticFiltersApplied ? "n.Neuron.Tag" : "n.Tag"; string sortOrder = neuronQuery.SortOrder.HasValue ? neuronQuery.SortOrder.Value.ToEnumString() : "ASC"; if (neuronQuery.SortBy.HasValue) { sortFieldName = neuronQuery.SortBy.Value.ToEnumString(); if (synapticFiltersApplied) { sortFieldName = "n." + sortFieldName; } else { if (sortFieldName.StartsWith("Neuron.")) { sortFieldName = sortFieldName.Replace("Neuron.", "n."); } else if (sortFieldName.StartsWith("Terminal.")) { sortFieldName = sortFieldName.Replace("Terminal.", "t."); } else { sortFieldName = sortFieldName[0].ToString().ToLower() + sortFieldName.Substring(1); } } } queryStringBuilder.Insert(lastReturnIndex, $"SORT {sortFieldName} {sortOrder} LIMIT @offset, @count RETURN"); queryParameters.Add(new QueryParameter() { Name = "offset", Value = NeuronRepository.CalculateOffset(neuronQuery.Page.Value, neuronQuery.PageSize.Value) }); queryParameters.Add(new QueryParameter() { Name = "count", Value = neuronQuery.PageSize.Value }); return(queryStringBuilder.ToString()); }