/// <summary> /// Returns a collection of nodes whose release date falls before /// </summary> /// <param name="start">The DateTime to use as the lower bound of the search</param> /// <param name="end">The DateTime to use as the upper bound of the search</param> /// <returns>A collection of nodes whose release date is in the specified range</returns> public List <BasicNodeModel> GetNodesBetweenDates(DateTime start, DateTime end) { List <BasicNodeModel> nodeModels = new List <BasicNodeModel>(); using (ISession session = driver.Session()) { // Create a transaction session.ReadTransaction(action => { IStatementResult result = action.Run("MATCH (n) WHERE (n.releaseDate >= $lowerBound AND n.releaseDate <= $upperBound) OR (n.deathDate >= $lowerBound AND n.deathDate <= $upperBound) RETURN n", new Dictionary <string, object> { { "lowerBound", DateValueConverter.ToLongValue(start) }, { "upperBound", DateValueConverter.ToLongValue(end) } }); // Add the nodes foreach (IRecord record in result) { nodeModels.Add(BasicNodeModel.FromINode(record[0].As <INode>())); } }); } return(nodeModels); }
/// <summary> /// Adds the given node to the database using a Apache Cassandra BATCH statement. /// </summary> /// <param name="node">The node to add to the database</param> public void AddNode(BasicNodeModel node) { using (ISession session = connection.Connect(autocompleteKeySpace)) { // Create the metadata statement PreparedStatement metadataStatement = session.Prepare( $"INSERT INTO {autocompleteMetadataTable} (id, prefixValues, remainingValues) VALUES (?, ?, ?)"); // Create the names table statement PreparedStatement mainStatement = session.Prepare( $"INSERT INTO {autocompleteTable} (prefix, remaining, id, name, commonName, dataType) VALUES (?, ?, ?, ?, ?, ?) IF NOT EXISTS"); // Add the original node InsertNode(node, session, metadataStatement, mainStatement); // For each of the related nodes... foreach (RelationshipModel relationship in node.Relationships) { // If the node is a new addition, if (relationship.IsNewAddition) { // Add the related node to the batch InsertNode(new BasicNodeModel { Id = relationship.TargetId.Value, CommonName = relationship.TargetName, ContentType = relationship.TargetType }, session, metadataStatement, mainStatement); } } } }
public BasicNodeModel GetNodeAndRelationships(Guid id) { BasicNodeModel node = null; using (ISession session = driver.Session()) { session.ReadTransaction(action => { IStatementResult statementResult = action.Run(kMatchNodeAndRelationshipsQuery, new Dictionary <string, object> { { "id", id.ToString() } }); // Get the relationships foreach (IRecord record in statementResult) { if (node == null) { node = BasicNodeModel.FromINode(record[0].As <INode>()); } node.AddRelationship(record["r"].As <IRelationship>(), record["e"].As <INode>()); } }); } return(node); }
/// <summary> /// Updates the given node within the autocomplete database. /// </summary> /// <param name="node">The node to update</param> public void UpdateNode(BasicNodeModel node) { // Remove the node from the database DeleteNode(node.Id.ToString()); // Add the node to the database AddNode(node); }
public ActionResult GetNodeInformation(Guid id) { BasicNodeModel model = new BasicNodeModel(); if(id != Guid.Empty) { using (NeoDriver driver = new NeoDriver()) { model = driver.GetNode(id); } } return Json(model, JsonRequestBehavior.AllowGet); }
/// <summary> /// Creates a group of creation statements for the given node that adds the referenced /// nodes 10 at a time. /// </summary> /// <param name="model">The node for which to generate the creation statements</param> /// <returns>A collection of statements that will be used to create the node</returns> private List <Statement> GenerateStatements(BasicNodeModel model) { List <Statement> creationStatements = new List <Statement>(); // For each of the relationships... foreach (RelationshipModel relModel in model.Relationships) { // Create the statement for the relationship creationStatements.Add(GenerateRelationshipStatement(relModel, model.ContentType)); } return(creationStatements); }
/// <summary> /// Updates the given node within the database system. /// </summary> /// <param name="node">The node to update</param> public void UpdateNode(BasicNodeModel node) { // Update the node in the autocomplete database using (CassandraDriver autocompleteDriver = new CassandraDriver()) { autocompleteDriver.UpdateNode(node); } // Update the node in the graph database using (NeoDriver graphDriver = new NeoDriver()) { graphDriver.UpdateNode(node); } }
/// <summary> /// Adds the given node into the database system. /// </summary> /// <param name="node">The node to add to the system</param> public void AddNode(BasicNodeModel node) { // Add the node into the autocomplete database using (CassandraDriver autocompleteDriver = new CassandraDriver()) { autocompleteDriver.AddNode(node); } // Add the node to the graph using (NeoDriver graphDriver = new NeoDriver()) { graphDriver.AddNode(node); } }
/// <summary> /// Adds the given node to the graph. /// PRECONDITION: The node must be valid /// </summary> /// <param name="node">The BasicNodeModel of the node to add to the graph</param> /// <returns>Returns true if the node was added to the graph successfully</returns> public bool AddNode(BasicNodeModel node) { // The total number of nodes that should be created int expectedNodeCount = node.Relationships.Where(x => x.IsNewAddition).Count() + 1; int expectedRelationshipCount = node.Relationships.Count(); int actualNodeCount = 0; int actualRelationshipCount = 0; // Get the statements that need to be run List <Statement> creationStatements = GenerateStatements(node); // Create the session using (ISession session = driver.Session()) { // Add the source node session.WriteTransaction(action => { IStatementResult nodeResult = action.Run(new Statement($"CREATE (s:{node.GetNodeLabels()} $props)", new Dictionary <string, object> { { "props", node.GetPropertyMap() } })); actualNodeCount += nodeResult.Summary.Counters.NodesCreated; // Only continue if the node was added if (actualNodeCount == 1) { // For each of the relationship statements, foreach (Statement relStatement in creationStatements) { // Run the statement IStatementResult relResult = action.Run(relStatement); // Update the counts of the actual node and relationship values actualNodeCount += relResult.Summary.Counters.NodesCreated; actualRelationshipCount += relResult.Summary.Counters.RelationshipsCreated; } } // If the node and relationship counts do not equal the expected values, if (actualNodeCount != expectedNodeCount || actualRelationshipCount != expectedRelationshipCount) { // This transaction has failed action.Failure(); } else { // This transaction has succeeded action.Success(); } }); } return(actualNodeCount == expectedNodeCount && actualRelationshipCount == expectedRelationshipCount); }
/// <summary> /// Creates a single large query for the creation of a node and it's direct relationships. /// </summary> /// <param name="model">The for which to create the creation query</param> /// <returns>The query string for the creation of the node and its direct relationships</returns> private string BuildNodeCreationQuery(BasicNodeModel model) { StringBuilder builder = new StringBuilder(); // Append the node creation statement builder.AppendFormat(kNodeCreationStatement, model.GetNodeLabels()); builder.AppendLine(); // Append the relationship statements BuildRelationshipMergeStatement(builder, model.Relationships, model.ContentType); // Append the return statement builder.Append("RETURN n"); return(builder.ToString()); }
public ActionResult FlagDeletion(Guid id) { string message = "An error occurred. The node was not flagged"; Response.StatusCode = (int)HttpStatusCode.InternalServerError; BasicNodeModel toDelete = null; using (NeoDriver driver = new NeoDriver()) { toDelete = driver.GetNode(id); } // If the node with the given id is not null, if (toDelete != null) { DatabaseRequest request = new DatabaseRequest { Id = Guid.NewGuid(), RequestType = DatabaseRequestType.Delete, SubmissionDate = DateTime.Now, NodeDataType = toDelete.ContentType, NodeData = JsonConvert.SerializeObject(BasicNodeViewModel.FromModel(toDelete)), Approved = false, ApprovalDate = null, Notes = null, Reviewed = false, ReviewedDate = null, Reviewer = null, ReviewerRefId = null }; // Add a deletion request, using (ApplicationDbContext context = ApplicationDbContext.Create()) { request.Submitter = context.Users.Single(u => u.UserName == User.Identity.Name); context.Requests.Add(request); context.SaveChanges(); } message = "Node flagged for deletion"; Response.StatusCode = (int)HttpStatusCode.Accepted; } else { message = "Could not find the specified node."; Response.StatusCode = (int)HttpStatusCode.NotFound; } return(Json(new { message = message })); }
/// <summary> /// Adds the given node into the database system. /// </summary> /// <param name="node">The node to add to the system</param> public void AddNode(BasicNodeModel node) { // Map the node's information for information marked as "New addition" MapNewAdditions(ref node); // Add the node into the autocomplete database using (CassandraDriver autocompleteDriver = new CassandraDriver()) { autocompleteDriver.AddNode(node); } // Add the node to the graph using (NeoDriver graphDriver = new NeoDriver()) { graphDriver.AddNode(node); } }
public BasicNodeModel GetNode(Guid id) { INode result; using (ISession session = driver.Session()) { result = session.ReadTransaction(action => { IStatementResult statementResult = action.Run(kMatchNodeQuery, new Dictionary <string, object> { { "id", id.ToString() } }); return(statementResult.FirstOrDefault()?[0].As <INode>()); }); } return(result != null?BasicNodeModel.FromINode(result) : null); }
public ActionResult TimelineData(Guid? id, string text) { BasicNodeModel model = null; using (NeoDriver driver = new NeoDriver()) { if(!id.HasValue || id == Guid.Empty) { model = driver.GetNode(text); } else { model = driver.GetNode(id.Value); } } return Json(new { success = model != null, ReleaseDate = model?.ReleaseDate, DeathDate = model?.DeathDate }, JsonRequestBehavior.AllowGet); }
/// <summary> /// Adds the given node to the graph. /// PRECONDITION: The node must be valid /// </summary> /// <param name="node">The BasicNodeModel of the node to add to the graph</param> /// <returns>Returns true if the node was added to the graph successfully</returns> public bool AddNode(BasicNodeModel node) { INode sessionResult; // Create the session using (ISession session = driver.Session()) { // Run the statement in a transaction sessionResult = session.WriteTransaction(action => { // Create the node IStatementResult result = action.Run(BuildNodeCreationQuery(node), new { props = node.GetPropertyMap() }); return(result.Single()[0].As <INode>()); }); } Program.LogInColor($"Neo4j: Added {node.CommonName} with id {node.Id} to graph.", ConsoleColor.DarkGreen); return(sessionResult != null); }
/// <summary> /// Inserts the given node into the Apache Cassandra autocomplete database. /// </summary> /// <param name="node">The node to add to the database</param> /// <param name="session">The session to use</param> /// <param name="metaStatement">The prepared metadata statement</param> /// <param name="mainStatement">The prepared main statement</param> private void InsertNode(BasicNodeModel node, ISession session, PreparedStatement metaStatement, PreparedStatement mainStatement) { Dictionary <string, Tuple <string, string> > bindingDictionary = GetBindingDictionary(node); // Get the id string once instead of everytime it is needed string idString = node.Id.ToString(); // Execute the meta statement //Console.WriteLine("ADDING TO META: " + node.CommonName + " WITH ID: " + node.Id.ToString()); session.Execute(metaStatement.Bind(idString, bindingDictionary.Select(x => x.Value.Item1).ToArray(), bindingDictionary.Select(x => x.Value.Item2).ToArray())); // For each of the entries in the binding dictionary... foreach (KeyValuePair <string, Tuple <string, string> > bindingEntry in bindingDictionary) { //Console.WriteLine("ADDING TO MAIN: " + bindingEntry.Key); // Execute the main statement session.Execute(mainStatement.Bind(bindingEntry.Value.Item1, bindingEntry.Value.Item2, idString, bindingEntry.Key, node.CommonName, (int)node.ContentType)); } }
// GET: Edit/Index/ public ActionResult Index(string id) { ActionResult result = View("Error"); if (!string.IsNullOrWhiteSpace(id)) { // Try to parse the Guid string Guid parsedId; if (Guid.TryParse(id, out parsedId)) { // The string was parsed, find the node // We have been given an id of a node to edit ViewBag.Title = "Edit Node Data"; BasicNodeViewModel viewModel = null; // Get the node to edit using (NeoDriver driver = new NeoDriver()) { BasicNodeModel model = driver.GetNodeAndRelationships(parsedId); viewModel = BasicNodeViewModel.FromModel(model); } // Return a view if (viewModel != null) { result = View(model: viewModel); } } else { Response.StatusCode = (int)HttpStatusCode.BadRequest; Response.StatusDescription = $"Invalid id value: {id}"; } } else { // We are creating a new node ViewBag.Title = "Create New Node"; result = View(model: new BasicNodeViewModel { Id = Guid.NewGuid(), ContentType = 0 }); } return(result); }
/// <summary> /// Inserts the given node into the Apache Cassandra autocomplete database. /// </summary> /// <param name="node">The node to add to the database</param> /// <param name="session">The session to use</param> /// <param name="metaStatement">The prepared metadata statement</param> /// <param name="mainStatement">The prepared main statement</param> private void InsertNode(BasicNodeModel node, ISession session, PreparedStatement metaStatement, PreparedStatement mainStatement) { Program.LogInColor($"Cassandra: Adding {node.CommonName}", ConsoleColor.DarkMagenta); Dictionary <string, Tuple <string, string> > bindingDictionary = GetBindingDictionary(node); // Get the id string once instead of everytime it is needed string idString = node.Id.ToString(); // Execute the meta statement session.Execute(metaStatement.Bind(idString, bindingDictionary.Select(x => x.Value.Item1).ToArray(), bindingDictionary.Select(x => x.Value.Item2).ToArray())); Program.LogInColor($"\tAdded {node.CommonName} to meta table with id {node.Id.ToString()}", ConsoleColor.DarkMagenta); // For each of the entries in the binding dictionary... foreach (KeyValuePair <string, Tuple <string, string> > bindingEntry in bindingDictionary) { // Execute the main statement session.Execute(mainStatement.Bind(bindingEntry.Value.Item1, bindingEntry.Value.Item2, idString, bindingEntry.Key, node.CommonName, (int)node.ContentType)); Program.LogInColor($"\tAdded {bindingEntry.Key} to main table", ConsoleColor.DarkMagenta); } }
/// <summary> /// Uses the autocomplete database to map node information to existing information. /// </summary> /// <param name="node">The node to map</param> private void MapNewAdditions(ref BasicNodeModel node) { // Get the referenced nodes that are marked as new additions IEnumerable <RelationshipModel> newAdditions = node.Relationships.Where(x => x.IsNewAddition); using (CassandraDriver driver = new CassandraDriver()) { // For each of the new additions foreach (RelationshipModel m in newAdditions) { // Search for an existing record List <AutocompleteRecord> existingRecords = driver.MappingSearch(m.TargetName, m.TargetType); // If there is exactly one record, if (existingRecords.Count == 1) { // Update the id to the existing record m.TargetId = Guid.Parse(existingRecords.First().Id); } } } }
/// <summary> /// Creates a dictionary containing the names values that will be bound to the /// main table statement when the node is added to the Apache Cassandra database. /// </summary> /// <param name="node">The node for which to get the binding values</param> /// <returns>A dictionary containing the binding values for each of the given node's names</returns> private Dictionary <string, Tuple <string, string> > GetBindingDictionary(BasicNodeModel node) { // Create the dictionary and add the commonName to the dictionary Dictionary <string, Tuple <string, string> > dictionary = new Dictionary <string, Tuple <string, string> > { { node.CommonName, BindName(node.CommonName) } }; // If there is a collection of other names, if (node.OtherNames != null) { // Add each of the other names to the dictionary foreach (string otherName in node.OtherNames) { dictionary.Add(otherName, BindName(otherName)); } } // Return the dictionary as a list return(dictionary); }
public BasicNodeModel GetNode(string commonName) { if (commonName == null) { return(null); } INode result = null; using (ISession session = driver.Session()) { result = session.ReadTransaction(action => { IStatementResult statementResult = action.Run(kMatchNodeByNameQuery, new Dictionary <string, object> { { "name", commonName } }); return(statementResult.FirstOrDefault()?[0].As <INode>()); }); } return(result != null?BasicNodeModel.FromINode(result) : null); }
private GraphDataViewModel GetPaths(Guid? id, string searchText) { GraphDataViewModel result = null; // Get the paths from the database List<IPath> paths = new List<IPath>(); using (NeoDriver driver = new NeoDriver()) { if(id == null || id == Guid.Empty) { paths = driver.GetPaths(searchText.ToLower()); } else { paths = driver.GetPaths(id.Value); } if(paths.Count == 0) { BasicNodeModel model = id == null || id == Guid.Empty ? driver.GetNode(searchText) : driver.GetNode(id.Value); if(model != null) { result.Source = new GraphNodeViewModel { Id = model.Id.ToString(), CommonName = model.CommonName, DataType = model.ContentType }; result.RelatedNodes = new List<GraphNodeViewModel>(); } } else { result = ConvertFromPaths(paths); } } return result; }
/// <summary> /// Constructs a node view model from the given node model. /// </summary> /// <param name="model">The node model for which to create a view model</param> /// <returns>The created view model</returns> public static BasicNodeViewModel FromModel(BasicNodeModel model) { BasicNodeViewModel result = null; if (model.ContentType == NodeContentType.Company) { result = new CompanyNodeViewModel(); } else if (model.ContentType == NodeContentType.Media) { result = new MediaNodeViewModel { MediaType = ((MediaNodeModel)model).MediaType, FranchiseName = ((MediaNodeModel)model).Franchise, Genres = ((MediaNodeModel)model).Genres, }; } else if (model.ContentType == NodeContentType.Person) { result = new PersonNodeViewModel { GivenName = ((PersonNodeModel)model).GivenName, FamilyName = ((PersonNodeModel)model).FamilyName, Status = ((PersonNodeModel)model).Status }; } // Add basic information result.Id = model.Id; result.ContentType = model.ContentType; result.CommonName = model.CommonName; result.OtherNames = model.OtherNames; result.ReleaseDate = model.ReleaseDate.HasValue ? DateValueConverter.ToDateTime(model.ReleaseDate.Value) : default(DateTime?); result.DeathDate = model.DeathDate.HasValue ? DateValueConverter.ToDateTime(model.DeathDate.Value) : default(DateTime?); // Add the relationships result.Relationships = ConvertRelationships(model.Relationships); return(result); }
public bool UpdateNode(BasicNodeModel model) { bool success = false; using (ISession session = driver.Session()) { success = session.ReadTransaction(action => { IStatementResult result = action.Run(kMatchNodeQuery, new Dictionary <string, object> { { "id", model.Id.ToString() } }); // We found a node to delete if (result.FirstOrDefault() != null) { // Delete the node Delete(action, model.Id); } // Update the node return(Update(action, model)); }); } return(success); }
/// <summary> /// Asynchronously adds the given node to the database system. /// </summary> /// <param name="node">The node to add to the database system</param> public async void AddNodeAsync(BasicNodeModel node) { await Task.Run(() => { AddNode(node); }); }
private bool Update(ITransaction transaction, BasicNodeModel node) { return(transaction.Run(BuildNodeCreationQuery(node), new { props = node.GetPropertyMap() }).Summary.Counters.NodesCreated > 0); }
/// <summary> /// Asynchronously updates the given node within the database system. /// </summary> /// <param name="node">The node to update</param> public async void UpdateNodeAsync(BasicNodeModel node) { await Task.Run(() => { UpdateNode(node); }); }