//todo: don't want to do this for embedded items private async Task <IEnumerable <INodeWithOutgoingRelationships> > GetIncomingPreviewContentPickerRelationshipsWhenPublishing( IGraphReplicaSet graphReplicaSet, dynamic graphSyncPartContent, string contentItemId) { // we only need to recreate incoming relationships // if we're publishing and there isn't currently a published version if (graphReplicaSet.Name != GraphReplicaSetNames.Published || await _contentItemsService.HasExistingPublishedVersion(contentItemId)) { return(Enumerable.Empty <INodeWithOutgoingRelationships>()); } // allow sync is called concurrently for preview and published // so we could get the before or after incoming relationships // either should do, but perhaps we should do it serially to consistently fetch the _before_ incoming relationships? IGetIncomingContentPickerRelationshipsQuery getDraftRelationshipsQuery = _serviceProvider.GetRequiredService <IGetIncomingContentPickerRelationshipsQuery>(); getDraftRelationshipsQuery.NodeLabels = MergeNodeCommand.NodeLabels; getDraftRelationshipsQuery.IdPropertyName = MergeNodeCommand.IdPropertyName; getDraftRelationshipsQuery.IdPropertyValue = _syncNameProvider.GetNodeIdPropertyValue( graphSyncPartContent, _previewContentItemVersion); IEnumerable <INodeWithOutgoingRelationships?> incomingContentPickerRelationshipsOrDefault = await _graphCluster.Run(_previewContentItemVersion.GraphReplicaSetName, getDraftRelationshipsQuery); #pragma warning disable S1905 // Sonar needs updating to know about nullable references return(incomingContentPickerRelationshipsOrDefault .Where(n => n != null) .Cast <INodeWithOutgoingRelationships>()); #pragma warning restore S1905 }
public async Task<IActionResult> SearchLookupNodes(string part, string content, string query) { if (string.IsNullOrWhiteSpace(part) || string.IsNullOrWhiteSpace(content)) { return BadRequest("Part and content are required parameters"); } var settings = _contentDefinitionManager .GetTypeDefinition(content) ?.Parts?.FirstOrDefault(p => p.Name == part) ?.GetSettings<GraphLookupPartSettings>(); if (settings == null) { return BadRequest("Unable to find field settings"); } //todo: interface and get from service provider //todo: add lookup graph to settings var results = await _neoGraphCluster.Run(GraphReplicaSetNames.Published, new LookupQuery( query, settings.NodeLabel!, //todo: check can these be null (when no values entered in settings)? settings.DisplayFieldName!, settings.ValueFieldName!)); return new ObjectResult(results); }
public async Task DeleteNodesByType(string graphReplicaSetName, string contentType) { if (string.IsNullOrWhiteSpace(contentType)) { return; } _logger.LogInformation("Sync: deleting all nodes of {ContentType}", contentType); _syncNameProvider.ContentType = contentType; _deleteNodesByTypeCommand.NodeLabels.UnionWith(await _syncNameProvider.NodeLabels(contentType)); try { await _graphCluster.Run(graphReplicaSetName, _deleteNodesByTypeCommand); } //todo: specify which exceptions to handle? catch { // this forces a rollback of the current OC db transaction _session.Cancel(); throw; } }
public async Task <IQueryResults?> ExecuteQueryAsync(Query query, IDictionary <string, object> parameters) { if (!(query is CypherQuery cypherQuery)) { return(null); } var parameterValues = BuildParameters(cypherQuery.Parameters, parameters); var result = new CypherQueryResult(); //todo: need to handle nulls var genericCypherQuery = new GenericCypherQuery(cypherQuery.Template !, parameterValues !); //todo: allow user to run queries against either graph. new story var cypherResult = await _neoGraphCluster.Run(GraphReplicaSetNames.Published, genericCypherQuery); if (cypherResult.Any()) { var collections = cypherResult.FirstOrDefault(); if (collections != null) { result.Items = TransformResults(cypherQuery.ResultModelType, collections); } } return(result); }
public async Task GraphConnectorRunReturnsSuccess(GraphReplicaSet graphReplicaSet) { // arrange var commands = new List <string> { "command one", "command two", }; A.CallTo(() => fakeServiceProvider.GetService(typeof(ICustomCommand))).Returns(new CustomCommand()); // act await graphConnector.RunAsync(commands, graphReplicaSet).ConfigureAwait(false); // assert A.CallTo(() => fakeServiceProvider.GetService(typeof(ICustomCommand))).MustHaveHappened(commands.Count, Times.Exactly); A.CallTo(() => fakeGraphCluster.Run(A <string> .Ignored, A <ICommand[]> .Ignored)).MustHaveHappenedOnceExactly(); Assert.True(true); }
private async Task <IEnumerable <string> > ExecuteSynonymQueryAsync(MatchSynonymsQuery query) { List <IRecord> result = await _neoGraphCluster.Run(GraphReplicaSetNames.Published, query); //todo: (at least some of) this code belongs in the queries ProcessRecord() //todo: revisit null handling IReadOnlyDictionary <string, object>?synonymResults = (IReadOnlyDictionary <string, object>?)result.FirstOrDefault()?.Values["results"]; return(((List <object>?)synonymResults?.Values.FirstOrDefault())?.OfType <string>() ?? Enumerable.Empty <string>()); }
private async Task <IEnumerable <string> > ExecuteSynonymQueryAsync(MatchSynonymsQuery query) { var result = await _neoGraphCluster.Run(GraphReplicaSetNames.Published, query); IReadOnlyDictionary <string, object> synonymResults = (IReadOnlyDictionary <string, object>)result.FirstOrDefault().Values["results"]; var synonymList = ((List <object>)synonymResults.Values.FirstOrDefault()).OfType <string>(); return(synonymList); }
private async Task <string?> GetNodeValue(string id, GraphLookupPartSettings settings) { //todo: check if settings can be null //todo: interface and get from service provider //todo: add which graph to lookup to settings var results = await _graphCluster.Run(GraphReplicaSetNames.Published, new GetPropertyOnNodeQuery( settings.NodeLabel !, settings.ValueFieldName !, id, settings.DisplayFieldName !)); return(results.First()); }
private async Task <IEnumerable <IRecord> > ExecuteCypherQuery(string query, ILogger log) { log.LogInformation($"Attempting to query neo4j with the following query: {query}"); try { return(await _graphCluster.Run("target", new GenericCypherQuery(query))); } catch (Exception ex) { throw ApiFunctionException.InternalServerError("Unable To run query", ex); } }
public async Task <List <TModel> > ExecuteCypherQuery <TModel>(GraphReplicaSet graphReplicaSet, string query) where TModel : class, new() { string replicaSetName = graphReplicaSet switch { GraphReplicaSet.Published => graphOptions.PublishedReplicaSetName, GraphReplicaSet.Draft => graphOptions.DraftReplicaSetName, _ => throw new NotImplementedException(), }; var result = await graphCluster.Run(replicaSetName, new GenericCypherQueryModel <TModel>(query)).ConfigureAwait(false); return(result); }
public async Task Execute_GetAllPages_ReturnsCorrectJsonResponse() { var recordJsonInput = File.ReadAllText(Directory.GetCurrentDirectory() + "/Files/Input/PageRecordInput_GetAll.json"); var expectedJsonOutput = File.ReadAllText(Directory.GetCurrentDirectory() + "/Files/Output/PageRecordOutput_GetAll.json"); A.CallTo(() => _graphCluster.Run(A <string> .Ignored, A <GenericCypherQuery> .Ignored)).Returns(new List <IRecord>() { new Api.Content.UnitTests.Models.Record(new string[] { "data.properties" }, new object[] { JsonConvert.DeserializeObject <Dictionary <string, object> >(recordJsonInput.ToString()) }) }); var result = await RunFunction("test1", null); var okObjectResult = result as OkObjectResult; // Assert Assert.True(result is OkObjectResult); var resultJson = JsonConvert.SerializeObject(okObjectResult.Value); var equal = JToken.DeepEquals(JToken.Parse(expectedJsonOutput), JToken.Parse(resultJson)); Assert.True(equal); }
public async Task RunAsync(IList <string>?commands) { _ = commands ?? throw new ArgumentNullException(nameof(commands)); var customCommands = new List <ICustomCommand>(); foreach (var command in commands) { var customCommand = serviceProvider.GetRequiredService <ICustomCommand>(); customCommand.Command = command; customCommands.Add(customCommand); } await graphCluster.Run(graphOptions.ReplicaSetName, customCommands.ToArray()).ConfigureAwait(false); }
public async Task <Subgraph> GetVisualisationSubgraph( string contentItemId, string graphName, IContentItemVersion contentItemVersion) { var relationshipCommands = await BuildVisualisationCommands(contentItemId, contentItemVersion !); // get all results atomically var result = await _neoGraphCluster.Run(graphName, relationshipCommands.ToArray()); var inAndOutResults = result.OfType <INodeAndOutRelationshipsAndTheirInRelationships?>(); //todo: should really always return the source node (until then, the subgraph will pull it if the main results don't) Subgraph subgraph; if (inAndOutResults.Any()) { // get all outgoing relationships from the query and add in any source nodes subgraph = new Subgraph( inAndOutResults .SelectMany(x => x !.OutgoingRelationships.Select(x => x.outgoingRelationship.DestinationNode)) .Union(inAndOutResults.GroupBy(x => x !.SourceNode).Select(z => z.FirstOrDefault() !.SourceNode)), inAndOutResults ! .SelectMany(y => y !.OutgoingRelationships.Select(z => z.outgoingRelationship.Relationship)) .ToHashSet(), inAndOutResults.FirstOrDefault()?.SourceNode); } else { subgraph = new Subgraph(); } ISubgraph?inResults = result.OfType <ISubgraph>().FirstOrDefault(); if (inResults != null) { subgraph.Add(inResults); } return(subgraph); }
public async Task RunAsync(IList <string>?commands, GraphReplicaSet graphReplicaSet) { _ = commands ?? throw new ArgumentNullException(nameof(commands)); string replicaSetName = graphReplicaSet switch { GraphReplicaSet.Published => graphOptions.PublishedReplicaSetName, GraphReplicaSet.Draft => graphOptions.DraftReplicaSetName, _ => throw new NotImplementedException(), }; var customCommands = new List <ICustomCommand>(); foreach (var command in commands) { var customCommand = serviceProvider.GetRequiredService <ICustomCommand>(); customCommand.Command = command; customCommands.Add(customCommand); } await graphCluster.Run(replicaSetName, customCommands.ToArray()).ConfigureAwait(false); }