Skip to content

Commit 55fe3d6

Browse files
authored
Add Redis Graph Commands (#37)
* Start Working Graph Module * Adding tests * Add Tests * Fix Some Tests * Add Commands * Fix Tests * Add Tests * Add Async Commands & Tests * Fixing some TODOs * Fix Test * Start Working on Transaction Tests * Fix Tests * Fix Tests * Add TestParseInfinity * Add TestMultiExec * Fixing TODOs * Fixing things * Delete Unnecessary Label Class * Delete Unnecessary Comments * Delete Property Class & Fix Tests * Efficiency of Lists and Naming * Naming & Cleanup * Nullable checks & Change Node Labels to public & PropertyToString * Mark as Comment the Transaction class * Add GetHashCode Method to class Header * Delete RedisGraphTransaction and fix GetIntValue warning * Delete comments * Add IGraphCommands * Fix Build Failure
1 parent 51b1717 commit 55fe3d6

27 files changed

+4060
-10
lines changed
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using System.Text;
2+
3+
namespace NRedisStack.Graph.DataTypes
4+
{
5+
/// <summary>
6+
/// A class reprenting an edge (graph entity). In addition to the base class properties, an edge shows its source,
7+
/// destination, and relationship type.
8+
/// </summary>
9+
public class Edge : GraphEntity
10+
{
11+
/// <summary>
12+
/// The relationship type.
13+
/// </summary>
14+
/// <value></value>
15+
public string RelationshipType { get; set; }
16+
17+
/// <summary>
18+
/// The ID of the source node.
19+
/// </summary>
20+
/// <value></value>
21+
public long Source { get; set; }
22+
23+
/// <summary>
24+
/// The ID of the desination node.
25+
/// </summary>
26+
/// <value></value>
27+
public long Destination { get; set; }
28+
29+
/// <summary>
30+
/// Overriden from the base `Equals` implementation. In addition to the expected behavior of checking
31+
/// reference equality, we'll also fall back and check to see if the: Source, Destination, and RelationshipType
32+
/// are equal.
33+
/// </summary>
34+
/// <param name="obj">Another `Edge` object to compare to.</param>
35+
/// <returns>True if the two instances are equal, false if not.</returns>
36+
public override bool Equals(object? obj)
37+
{
38+
if (obj == null) return this == null;
39+
40+
if (this == obj)
41+
{
42+
return true;
43+
}
44+
45+
if (!(obj is Edge that))
46+
{
47+
return false;
48+
}
49+
50+
if (!base.Equals(obj))
51+
{
52+
return false;
53+
}
54+
55+
return Source == that.Source && Destination == that.Destination && RelationshipType == that.RelationshipType;
56+
}
57+
58+
/// <summary>
59+
/// Overriden from base to compute a deterministic hashcode based on RelationshipType, Source, and Destination.
60+
/// </summary>
61+
/// <returns>An integer representing the hash code for this instance.</returns>
62+
public override int GetHashCode()
63+
{
64+
unchecked
65+
{
66+
int hash = 17;
67+
68+
hash = hash * 31 + base.GetHashCode();
69+
hash = hash * 31 + RelationshipType.GetHashCode();
70+
hash = hash * 31 + Source.GetHashCode();
71+
hash = hash * 31 + Destination.GetHashCode();
72+
73+
return hash;
74+
}
75+
}
76+
77+
/// <summary>
78+
/// Override from base to emit a string that contains: RelationshipType, Source, Destination, Id, and PropertyMap.
79+
/// </summary>
80+
/// <returns>A string containing a description of the Edge containing a RelationshipType, Source, Destination, Id, and PropertyMap.</returns>
81+
public override string ToString()
82+
{
83+
var sb = new StringBuilder();
84+
85+
sb.Append("Edge{");
86+
sb.Append($"relationshipType='{RelationshipType}'");
87+
sb.Append($", source={Source}");
88+
sb.Append($", destination={Destination}");
89+
sb.Append($", id={Id}");
90+
sb.Append($", {PropertyMapToString()}");
91+
sb.Append("}");
92+
93+
return sb.ToString();
94+
}
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using System.Text;
2+
3+
namespace NRedisStack.Graph.DataTypes
4+
{
5+
/// <summary>
6+
/// An abstract representation of a graph entity.
7+
/// A graph entity has an ID and a set of properties. The properties are mapped and accessed by their names.
8+
/// </summary>
9+
public abstract class GraphEntity
10+
{
11+
public long Id { get; set; }
12+
13+
public IDictionary<string, object> PropertyMap = new Dictionary<string, object>();
14+
15+
/// <summary>
16+
/// Overriden Equals that considers the equality of the entity ID as well as the equality of the
17+
/// properties that each entity has.
18+
/// </summary>
19+
/// <param name="obj"></param>
20+
/// <returns></returns>
21+
public override bool Equals(object? obj)
22+
{
23+
if (obj == null) return this == null;
24+
25+
if (this == obj)
26+
{
27+
return true;
28+
}
29+
30+
if (!(obj is GraphEntity that))
31+
{
32+
return false;
33+
}
34+
35+
return Id == that.Id && (PropertyMap.SequenceEqual(that.PropertyMap));
36+
}
37+
38+
/// <summary>
39+
/// Overriden GetHashCode that computes a deterministic hash code based on the value of the ID
40+
/// and the name/value of each of the associated properties.
41+
/// </summary>
42+
/// <returns></returns>
43+
public override int GetHashCode()
44+
{
45+
unchecked
46+
{
47+
int hash = 17;
48+
49+
hash = hash * 31 + Id.GetHashCode();
50+
51+
foreach(var prop in PropertyMap)
52+
{
53+
hash = hash * 31 + prop.Key.GetHashCode();
54+
hash = hash * 31 + prop.Value.GetHashCode();
55+
}
56+
57+
return hash;
58+
}
59+
}
60+
61+
/// <summary>
62+
/// Overriden ToString that emits a string containing the ID and property map of the entity.
63+
/// </summary>
64+
/// <returns></returns>
65+
public override string ToString()
66+
{
67+
var sb = new StringBuilder();
68+
69+
sb.Append("GraphEntity{id=");
70+
sb.Append(Id);
71+
sb.Append(", propertyMap=");
72+
sb.Append(PropertyMap);
73+
sb.Append('}');
74+
75+
return sb.ToString();
76+
}
77+
78+
public string PropertyMapToString()
79+
{
80+
var sb = new StringBuilder();
81+
82+
sb.Append("propertyMap={");
83+
sb.Append(string.Join(", ", PropertyMap.Select(pm => $"{pm.Key}={pm.Value}")));
84+
sb.Append("}");
85+
86+
return sb.ToString();
87+
}
88+
}
89+
}
+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Text;
4+
5+
namespace NRedisStack.Graph.DataTypes
6+
{
7+
/// <summary>
8+
/// A class representing a node (graph entity). In addition to the base class ID and properties, a node has labels.
9+
/// </summary>
10+
public sealed class Node : GraphEntity
11+
{
12+
public List<string> Labels { get; }
13+
14+
public Node()
15+
{
16+
Labels = new List<string>();
17+
}
18+
19+
/// <summary>
20+
/// Overriden member that checks to see if the names of the labels of a node are equal
21+
/// (in addition to base `Equals` functionality).
22+
/// </summary>
23+
/// <param name="obj"></param>
24+
/// <returns></returns>
25+
public override bool Equals(object? obj)
26+
{
27+
if (obj == null) return this == null;
28+
29+
if (this == obj)
30+
{
31+
return true;
32+
}
33+
34+
if (!(obj is Node that))
35+
{
36+
return false;
37+
}
38+
39+
if (!base.Equals(obj))
40+
{
41+
return false;
42+
}
43+
44+
return Enumerable.SequenceEqual(Labels, that.Labels);
45+
}
46+
47+
/// <summary>
48+
/// Overridden member that computes a hash code based on the base `GetHashCode` implementation
49+
/// as well as the hash codes of all labels.
50+
/// </summary>
51+
/// <returns></returns>
52+
public override int GetHashCode()
53+
{
54+
unchecked
55+
{
56+
int hash = 17;
57+
58+
foreach(var label in Labels)
59+
{
60+
hash = hash * 31 + label.GetHashCode();
61+
}
62+
63+
hash = hash * 31 + base.GetHashCode();
64+
65+
return hash;
66+
}
67+
}
68+
69+
/// <summary>
70+
/// Overridden member that emits a string containing the labels, ID, and property map of a node.
71+
/// </summary>
72+
/// <returns></returns>
73+
public override string ToString()
74+
{
75+
var sb = new StringBuilder();
76+
77+
sb.Append("Node{labels=");
78+
sb.Append($"[{string.Join(", ", Labels)}]");
79+
sb.Append($", id={Id}");
80+
sb.Append($", {PropertyMapToString()}");
81+
sb.Append("}");
82+
83+
return sb.ToString();
84+
}
85+
}
86+
}
+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System.Collections.ObjectModel;
2+
using System.Runtime.CompilerServices;
3+
using System.Text;
4+
5+
[assembly: InternalsVisibleTo("NRedisStack.Tests.Graph")]
6+
7+
namespace NRedisStack.Graph.DataTypes
8+
{
9+
/// <summary>
10+
/// This class represents a path in the graph.
11+
/// </summary>
12+
public class Path
13+
{
14+
public ReadOnlyCollection<Node> Nodes { get;}
15+
public ReadOnlyCollection<Edge> Edges { get;}
16+
17+
public Path(IList<Node> nodes, IList<Edge> edges)
18+
{
19+
Nodes = new ReadOnlyCollection<Node>(nodes);
20+
Edges = new ReadOnlyCollection<Edge>(edges);
21+
}
22+
23+
24+
/// <summary>
25+
/// How many edges exist on this path.
26+
/// </summary>
27+
public int Length => Edges.Count;
28+
29+
/// <summary>
30+
/// Overriden `Equals` method that will consider the equality of the Nodes and Edges between two paths.
31+
/// </summary>
32+
/// <param name="obj"></param>
33+
/// <returns></returns>
34+
public override bool Equals(object? obj)
35+
{
36+
if (obj == null) return this == null;
37+
38+
if (this == obj)
39+
{
40+
return true;
41+
}
42+
43+
if (!(obj is Path path))
44+
{
45+
return false;
46+
}
47+
48+
return Enumerable.SequenceEqual(Nodes, path.Nodes) && Enumerable.SequenceEqual(Edges, path.Edges);
49+
}
50+
51+
/// <summary>
52+
/// Overridden `GetHashCode` method that will compute a hash code using the hash code of each node and edge on
53+
/// the path.
54+
/// </summary>
55+
/// <returns></returns>
56+
public override int GetHashCode()
57+
{
58+
unchecked
59+
{
60+
int hash = 17;
61+
62+
foreach (var node in Nodes)
63+
{
64+
hash = hash * 31 + node.GetHashCode();
65+
}
66+
67+
foreach (var edge in Edges)
68+
{
69+
hash = hash * 31 + edge.GetHashCode();
70+
}
71+
72+
return hash;
73+
}
74+
}
75+
76+
/// <summary>
77+
/// Overridden `ToString` method that will emit a string based on the string values of the nodes and edges
78+
/// on the path.
79+
/// </summary>
80+
/// <returns></returns>
81+
public override string ToString()
82+
{
83+
var sb = new StringBuilder();
84+
85+
sb.Append("Path{");
86+
sb.Append($"nodes={Nodes}");
87+
sb.Append($", edges={Edges}");
88+
sb.Append("}");
89+
90+
return sb.ToString();
91+
}
92+
}
93+
}

src/NRedisStack/Graph/GraphCache.cs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace NRedisStack.Graph
2+
{
3+
internal sealed class GraphCache
4+
{
5+
public GraphCacheList Labels { get; set; }
6+
public GraphCacheList PropertyNames { get; set; }
7+
public GraphCacheList RelationshipTypes { get; set; }
8+
9+
public GraphCache(string graphName, GraphCommands redisGraph)
10+
{
11+
Labels = new GraphCacheList(graphName, "db.labels", redisGraph);
12+
PropertyNames = new GraphCacheList(graphName, "db.propertyKeys", redisGraph);
13+
RelationshipTypes = new GraphCacheList(graphName, "db.relationshipTypes", redisGraph);
14+
}
15+
16+
public string GetLabel(int index) => Labels.GetCachedData(index);
17+
18+
public string GetRelationshipType(int index) => RelationshipTypes.GetCachedData(index);
19+
20+
public string GetPropertyName(int index) => PropertyNames.GetCachedData(index);
21+
22+
}
23+
}

0 commit comments

Comments
 (0)