Showing posts with label neo4j. Show all posts
Showing posts with label neo4j. Show all posts

Wednesday, July 17, 2013

Upgrading to JRuby | Neo4J | rvm on Ubuntu



While upgrading the Wikibrains server I encountered a few snags, I had to bypass these issues by following these steps:
Purging the RVM/Ruby installations: (source)
sudo apt-get --purge remove ruby-rvm
sudo rm -rf /usr/share/ruby-rvm /etc/rvmrc /etc/profile.d/rvm.sh
open new terminal and validate environment is clean from old RVM settings (should be no output):
env | grep rvm
if there was output, try to open new terminal, if it does not help then restart your computer.
\curl -L https://get.rvm.io | 
  bash -s stable --ruby --autolibs=enable --auto-dotfiles

Then Run:

source /usr/local/rvm/scripts/rvm

Now proceed to installing rails:

gem install rails --version '= 0.3.8'
gem install bundler

creating the application with neo4j.rb:
rails _3.2.8_ new myapp -m http://andreasronge.github.com/neo4j/rails.rb -O
note: at the time of this post, there is a conflict between Neo4j.rb and rails 4 dependencies.

Wednesday, August 1, 2012

Wikisrains moves to Public Beta phase

Months of hard work have finally resulted in airing the WikiBrains machine learning engine.
Having people using it is so exiting, since as more of them do, the smarted it gets.

Although one would need to register to actually use the brainstorm GUI tool, its easy to see the daily increase in vocabulary and context just by going into the search page and checking out 'Apple' (just an example).

Each time a user lines up a couple of words, may they be of his own design or using existing connections from the suggestion list, the brain is enriched by a new synapse.

The wiki engine uses a graph database to store the words as objective points and the subjective links between them are what people have to say about those words.

We still have several usability issues with the GUI, perhaps too cumbersome one may argue. but despite some snags on the way, it works (which makes me really happy). No performance issues so far, and the user base is steadily growing.

Thumbs up for the Wikibrains team!






.

Saturday, July 18, 2009

Down the rabbits hole with neo4j (Part 1)

While standing on one foot, I would say that the neo4j project is an implementation for an embedded java graph database. Unlike the traditional relation databases, the graph database has no table structure for storing its data. Instead it uses a more dynamic (unstructured) network composition. Using mathematical terminology, a network of nodes is called a graph.

I’ll put my other foot down now.

Applications use an object data structure in order to describe and abstract the business domain they address. Stitching together the object oriented structure onto the table oriented data structure of a relational database is a major part of the time consumed in server side programming. This price has been, and still is willingly paid because of the absolute reliability of the traditional relational data structures.

Truth to be said, there are implementations that make much more sense when persisted using tables. However, I would dare to argue that when querying becomes complex and cumbersome, it just might be a sign that the persisting method isn’t appropriate.

The unstructured graph database leads the field when it comes to implementing an ad-hoc structure that is prone to runtime changes.

I decided to give it a try after watching Emil Efirem’s demonstration on the web and I’m sharing my experience as I played around with three aspects of use:

  • Part 1: Converting plain java data objects into persisted neo nodes
  • Part 2: Managing lookups
  • Part 3: Experimenting With Transactions

Setting up a neo4j environment

The neo4j jars are available on: http://neo4j.org/download, under which there are two packages;

  • The apoc package includes some extra utility jars, i.e. the indexing jar, the shell jar and some examples
  • The kernel package includes the bare minimum, i.e. neo and jta jars

My example project’s source code is also available here, compatible for eclipse and intelliJ.

Part 1: Converting POJO into neo

In my mind’s eye I saw a plain old java data objects that would define my domain data structure. These objects would be passed to some kind of neo facilitating mechanism that would take care of the persistence for me.

Using annotations

Java annotations are a wonderful tool; I use Annotations to load metadata on class elements, when the metadata is not intended to be part of the primary business course of the class.

In this example, I have a type representing a person that has a couple of properties and lists of friends and foes. I annotated the fields with the hinting I needed to ease the conversion into neo.

Note that the conversion is handled at runtime so the annotation retention policy is set appropriately.

Here is the annotation declaration:

@Retention(RetentionPolicy.RUNTIME)
public @interface Persistance {
  Type type() default Type.Property;
  Peers relationType() default Peers.NA;
  public static enum Type {
    Property, Peer
  }
}

The annotated POJO, representing my person data is as follows:
public enum Peers implements RelationshipType {
  Friend, Foe, NA
}
public class Person {
  @Persistance(type = Persistance.Type.Property)
  public String name;

  @Persistance(type = Persistance.Type.Property)
  public String nickname;

  @Persistance(type = Persistance.Type.Peer, relationType = Peers.Friend)
  public List<Person> friends;

  @Persistance(type = Persistance.Type.Peer, relationType = Peers.Foe)
  public List<Person> foes;
And so on…

The conversion to the neo nodes

The neo world speaks in two basic terms, the node and the relation. Each can bear its own properties.

The nodes have no typing, which I think is a shame, but relationships do require typing. I went along with the recommendations and defined my relationship as an enum.

The snippet for the relationship type:
public enum Peers implements RelationshipType {
  Friend, Foe, NA
}
The persistence mechanism is a recursive breakdown of the POJO graph (the person and all this friends etc.) according to the hints I get on the annotations.

Within a neo transaction I call the converting method by passing the object I want to persist onto it:

    Transaction tx = neo.beginTx();
    Node node = null;
    try {
      node = objectToNode(object, null);
      tx.success();
      return node.getId();
    } catch (Exception e) {
      tx.failure();
      e.printStackTrace();
    } finally {
      tx.finish();
    }

The method objectToNode(..) is the recursive part and I load it with a stack map to prevent the recursive calls from looping forever on objects that were already processed.

    if (stack == null) {
      stack = new HashMap<Object, Node>();
    } else if (stack.containsKey(object)) {
      return stack.get(object);
    }
    Node node = neo.createNode();
    stack.put(object, node);
    Class cls = object.getClass();
    Field[] fields = cls.getDeclaredFields();
    for (Field field : fields) {
      // only persisting the fields that have my special annotation
      if (field.isAnnotationPresent(Persistance.class)) {
        processFieldData(node, object, field, stack);
      }
    }
    return node;

The method processFieldData(..) is where the annotations are processed. Properties are loaded on the nodes and hints for relationships invoke the recursive call that handles the linked objects as independent nodes.

      if (annotation instanceof Persistance) {
        Persistance p = (Persistance) annotation;
        log("processing annotation: " + p.type() + " "
            + p.relationType());
        if (p.type().equals(Persistance.Type.Property)) {
          // TODO: verify that the property is actually a primitive
          Object value = field.get(object);
          log("setting property: " + field.getName() + " " + value);
          // here is a neo setting of a property
          node.setProperty(field.getName(), value);
        } else if (p.type().equals(Persistance.Type.Peer)) {
          Object value = field.get(object);
          log("setting peer: " + field.getName() + " " + value);
          if (value instanceof List) {
            for (Object item : (List) value) {
              // here is another neo bit, where a new Node is
              // created by recursively calling on the converting
              // method with the child object
              // after the new node is handed back, i create the
              // relationship between the two
              Node otherNode = objectToNode(item, stack);
              node.createRelationshipTo(otherNode, p
                  .relationType());
            }
   

Download the complete java source code