Get a Taste of Graph Databases: InfoGrid, Neo4j and sones GraphDB
Alex Popescu, author of the well-known MyNoSQL blog recently wrote about a very (very) basic tagging app and its implementation within the InfoGrid and Neo4j graph database systems.
Today we want to pick up the given example and show you an implementation using the sones GraphDB and the GraphDBSharp API:
using System; using System.Linq; using System.Collections.Generic; using sones.GraphDB; using sones.GraphDB.Structures; using sones.GraphDB.API.CSharp; using sones.GraphDB.API.CSharp.Reflection; using sones.GraphDB.Connectors.GraphDBREST; using sones.GraphFS.Connectors.GraphFSCLI; using sones.GraphDB.Connectors.GraphDBCLI; namespace TagExample { public class Tag : DBObject { // Will inherit an UUID and RevisionID property from DBObject [CreateIndex(DBIndexTypes.HashTable)] public String Name { get; set; } // Backwardedges to the attribute Tags of type Websites [BackwardEdge("Tags")] public List TaggedWebsites { get; set; } public Tag() { } } public class Website : DBObject { // Will inherit an UUID and RevisionID property from DBObject [CreateIndex(DBIndexTypes.HashTable)] public String Name { get; set; } public String URL { get; set; } // Edges to the tags public List Tags { get; set; } public Website() { } } public class TagExample { private void CheckResult(QueryResult myQueryResult) { Console.WriteLine("{0} => {1}", myQueryResult.Query, myQueryResult.ResultType); } private void Run() { // Create a new in-memory database var GDB = new GraphDBSharp() { DatabaseName = "TagExampleDB", Username = "Dr.Falken", Password = "Joshua" // For persistence use: //StorageLocation = "file://TagExampleDB.fs", //StorageLocation = "net.tcp://127.0.0.1:8000", }; GDB.CreateDatabase(true); // Create types tag and website using reflection GDB.CreateTypes(CheckResult, new Tag(), new Website()); // Insert tags var _good = new Tag() { Name = "good" }; var _funny = new Tag() { Name = "funny" }; GDB.Insert(CheckResult, _good, _funny); // Insert websites and link them to their tags var _cnn = new Website() { Name = "CNN", URL = "http://cnn.com/", Tags = new List() { _good } }; var _xkcd = new Website() { Name = "xkcd", URL = "http://xkcd.com/", Tags = new List() { _good, _funny } }; var _onion = new Website() { Name = "onion", URL = "http://theonion.com/", Tags = new List() { _funny } }; GDB.Insert(CheckResult, _cnn, _xkcd, _onion); // Find out which tags xkcd is tagged with var _xkcdtags = GDB.Query("FROM Website w SELECT w.Tags " + "WHERE w.Name = 'xkcd' DEPTH 1"); foreach (var _tag in (List) _xkcdtags["Tags"]) Console.WriteLine(_tag["Name"]); // List tagged sites var _taggedsites = GDB.Query("FROM Website w SELECT w.Name, " + "Count(w.Tags) AS Counter " + "WHERE Count(w.Tags)>0"); foreach (var _sites in (List) _taggedsites[0]) Console.WriteLine("{0} => {1}", _sites["Name"], _sites["Counter"]); // Start a REST service on localhost port 9975 GDB.StartREST(new Uri("http://localhost:9975")); // Start the GraphDB command line interface GDB.OpenCLI(typeof(ABasicFSCLICommands), typeof(AAdvancedFSCLICommands), typeof(ABasicDBCLICommands), typeof(AAdvancedDBCLICommands)); GDB.Shutdown(); } public static void Main(string[] myArgs) { var w = new TagExample(); w.Run(); } } }
The current C# API is already very expressive, but other programming languages might be much more verbose. To avoid writing a lot of code, you can always use our Graph Query Lanuage (GraphQL) which is an optimized Domain-specific language (DSL) for creating and manipulating a graph within our database.
CREATE TYPES Tag EXTENDS DBObject ATTRIBUTES (String Name) BACKWARDEDGES (Website.Tags TaggedWebsites) INDICES (Name), Website EXTENDS DBObject ATTRIBUTES (String Name, String URL, LIST Tags) INDICES (Name) INSERT INTO Tag VALUES (Name = 'good') INSERT INTO Tag VALUES (Name = 'funny') INSERT INTO Website VALUES (Name = 'CNN', URL = 'http://cnn.com/', Tags = SETOF (Name = 'good')) INSERT INTO Website VALUES (Name = 'xkcd', URL = 'http://xkcd.com/', Tags = SETOF (Name = 'good', Name = 'funny')) INSERT INTO Website VALUES (Name = 'onion', URL = 'http://theonion.com/', Tags = SETOF (Name = 'funny')) // Find out which tags xkcd is tagged with... FROM Website w SELECT w.Tags WHERE w.Name = 'xkcd' DEPTH 1 // Alternative query... FROM Tag t SELECT t.Name WHERE t.TaggedWebsites.Name = 'xkcd' // List tagged sites... FROM Website w SELECT w.Name, Count(w.Tags) AS Counter WHERE Count(w.Tags)>0

On 24. February 2010 at 21:35
Fantastic! I’d really love to feature this code along with the others. Would you be OK with that? (just drop me an email if you agree).
And thanks a lot for picking up my challenge!
:- alex
MyNoSQL: All Things NoSQL
http://nosql.mypopescu.com
On 4. March 2010 at 10:56
[…] example illustrates the similarities and differences between the two graph implementations. A follow-up article from the sones developers shows an example of the same application in the .NET sones GraphDB […]
On 12. March 2010 at 14:47
[…] developers.sones.de » Get a Taste of Graph Databases: InfoGrid … […]
On 16. September 2010 at 00:49
Wouldn’t this look much prettier if you’d provide native LINQ support?
var taggedsites = from w in GDB.Query()
where w.Tags.Count() > 0
select new { w.Name, Counter = w.Tags.Count() };
foreach (var site in taggedSites)
Console.WriteLine (“{0} => {1}”, site.Name, site.Counter);
It would make a nice bullet point on your feature list too
If you’re interested, take a look at relinq.codeplex.com. You’d be in the same place as NHibernate, they use re-linq to go from LINQ to HQL, only that GQL should make an easier target. (Or contact me directly if you want to discuss support options.)
On 16. September 2010 at 11:09
your comments eat angle brackets.
from w in GDB.Query<Website>()
…
On 13. September 2011 at 18:16
Guys, can you please post more elaborated samples around the .net API.
The sample given above is even incomplete. When you go to GraphDSharp on github, you do not find the C# API there.
Seems like, you guys have done good job in writing the library, please spend some time on tech docs too.
Loved it. But frustrated.
On 14. September 2011 at 11:33
it’s mainly a problem of keeping the documentation in sync with the progress we are making with the technology. If you are working on the current master branch on github you’ll find a number of examples in the wiki we added in the last 3 months — documentation is a main focus and we’re going to expand the effort put into documentation in the future. If you got any question or suggestion please use the (also new) forum to write about it.
On 15. September 2011 at 14:24
The problem is I can not figure out how to implement (as part of POC) something using the C# library. The samples do not work, no proper documentation available, technical documentation is not comprehensive.
Sones surely could become industry leader if it becomes easy-to-use and easy-to-figure-out.
Can you please provide more documentation around API?
On 15. September 2011 at 15:58
If you can get an answer for a specific question.
I am trying to implement the University sample in C#. I have added City and University, now I want to add Edge between these two Vertices. Can you tell me how do I do it?
Much Appreciated.
On 15. September 2011 at 16:35
I think we can help you and get your code running — if you would please take the time to post your code including a short description which version of GraphDB you are currently using into our forum on http://forum.sones.de
On 15. September 2011 at 16:37
maybe you find some answers by taking a look at the most current API example: https://github.com/sones/sones/blob/master/Applications/TagExample/Example.cs
If you checkout out the current version of GraphDB (2.1-pre-release) you’ll see the tremendous amount of progress we are making — it’s always hard to keep the documentation current but we’re doing our best.
Some more information on the current API can be found here: http://developers.sones.de/wiki/doku.php?id=tutorials:tagexample
On 15. September 2011 at 17:49
I am using the same 2.1 version. I will try posting my exact problems on the forum.
Thanks for your help.
On 15. September 2011 at 18:04
Great! We appreciate it