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<Website> 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<Tag> 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<Tag>() { _good }
};
var _xkcd = new Website() {
Name = "xkcd",
URL = "http://xkcd.com/",
Tags = new List<Tag>() { _good, _funny }
};
var _onion = new Website() {
Name = "onion",
URL = "http://theonion.com/",
Tags = new List<Tag>() { _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<DBObjectReadout>) _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<DBObjectReadout>) _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 (GQL) 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<Tag> 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
