Yii 1.1: neo4yii

An ActiveRecord like wrapper for the (RESTful) Neo4j graph database
15 followers

Neo4Yii

This is an ActiveRecord like wrapper for the RESTful graph database Neo4j. I built this on top of my ActiveResource for Yii extension and although it isn't perfect (missing indexing support and bugs may still lurk) I share my work with the Yii community. This extension is still under development so heads up!

Futher information can be found at Neo4Yii at Github or at the forum thread

Installation:

Steps

  1. Download my ActiveResource extension and add it to your extensions folder (If you haven't done already).

  2. Download the Neo4Yii extension at Github, import EActiveResource and Neo4Yii and configure Neo4Yii this way:

'import'=>array(
                'application.extensions.EActiveResource.*',
                'application.extensions.Neo4Yii.*',
            )
 
            'neo4j'=>array(
                    'class'=>'ENeo4jGraphService',
                    'host'=>'192.168.2.10',
                    'port'=>'7474',
                    'db'=>'db/data',
                    'queryCacheID'=>'cache',
                ),

Usage

Example: Persons have friends which themselves can also have friends (via a friend relationship). Each friendship can be defined with the property "forYears". e.g.:Old friends know each other for more than 5 years. Here is an example of how to use Neo4Yii in such a case.

class Person extends ENeo4jNode
{
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
 
    public function properties()
    {
        return CMap::mergeArray(parent::properties(),array(
            'name'=>array('type'=>'string'),
            'surname'=>array('type'=>'string'),
            'age'=>array('type'=>'integer'),
            'gender'=>array('type'=>'string'),
        ));
    }
 
    public function rules()
    {
        return array(
            array('name,surname,age,gender','safe'),
            array('age','numerical','integerOnly'=>true),
            array('name','required')
        );
    }
 
    public function traversals()
    {
        return array(
            'friends'=>array(self::HAS_MANY,self::NODE,'out("_FRIEND_")'),
            'fof'=>array(self::HAS_MANY,self::NODE,'out("_FRIEND_").out("_FRIEND_")'),      'oldFriends'=>array(self::HAS_MANY,self::NODE,'outE("_FRIEND_").filter{it.forYears>5}.inV'),
        );
    }
}
class _FRIEND_ extends ENeo4jRelationship
{
    public static function model($className = __CLASS__) {
        return parent::model($className);
    }
 
    public function properties()
    {
        return CMap::mergeArray(parent::properties(),array(
            'forYears'=>array('type'=>'integer'),
        ));
    }
 
    public function rules()
    {
        return array(
            array('forYears','safe'),
            array('forYears','numerical'),
        );
    }
}
$haensel=new Person;
 
            $haensel->attributes=array(
                'name'=>'Johannes',
                'surname'=>'Bauer',
                'age'=>29,
                'gender'=>'m'
            );
            $haensel->save();
 
            $bill=new Person;
            $bill->attributes=array(
                'name'=>'Bill',
                'surname'=>'Brown',
                'age'=>26,
                'gender'=>'m'
            );
            $bill->save();
 
            $haensel->addRelationshipTo($bill, '_FRIEND_',array('forYears'=>10));
 
            $susan=new Person;
            $susan->attributes=array(
                'name'=>'Susan',
                'surname'=>'Scissors',
                'age'=>31,
                'gender'=>'f'
            );
            $susan->save();
 
            $haensel->addRelationshipTo($susan, '_FRIEND_',array('forYears'=>4));
 
            $susansFriend=new Person;
            $susansFriend->attributes=array(
                'name'=>'Susans',
                'surname'=>'Friend',
                'age'=>40,
                'gender'=>'m'
            );
            $susansFriend->save();
 
            $susan->addRelationshipTo($susansFriend, '_FRIEND_',array('forYears'=>4));
 
            echo 'Haensels friends:<br>';
            foreach($haensel->friends as $friend)
                echo $friend->name .' '.$friend->surname.'<br>';
 
            echo 'Haensels old friends:<br>';
            foreach($haensel->oldFriends as $oldFriend)
                echo $oldFriend->name .' '.$oldFriend->surname.'<br>';
 
            echo 'friends of Haensels friends:<br>';
            foreach($haensel->fof as $fof)
                echo $fof->name .' '.$fof->surname.'<br>';
 
            /*
            Haensels friends:
            Bill Brown
            Susan Scissors
            Haensels old friends:
            Bill Brown
            friends of Haensels friends:
            Susans Friend
            */

Total 10 comments

#16850 report it
Lidiexy at 2014/04/03 04:46pm
I can't work with this awesome Extension

Hi Haensel When i try to view your code example i got this PHP ERROR

Declaration of ENeo4jPropertyContainer::query() should be compatible with EActiveResource::query($route, $method = 'GET', $params = Array, $data = NULL)

Any advice?

Best Regards

#11106 report it
John1983 at 2012/12/17 07:06am
Remove relationship in neo4j

How to remove relationship in neo4j? Please help.

#6988 report it
HLii at 2012/02/17 09:06am
Thanks

I will open a ticket in GitHub.

haiyangl

#6984 report it
Haensel at 2012/02/17 04:45am
Hi again

Ah, I see your point. This should be quite easy to implement. But could you please open such issues/features add the Github project page so that I can keep track of such ideas?

Thanks!

Hannes

#6980 report it
HLii at 2012/02/16 09:26pm
Relationship

Hi, Haensel,

Thank you for add the indexing feature and I am still work on using. I'll post some feedback once I finish my test.

I have one request for your to consider.

Currently the setStartNode and setEndNode takes ENeo4jNode as input. Is it possible to also have them accept integer as input? I am working on something, I've already cached the node ID somewhere in the application. It will be great if I can just pass the node ID to these 2 method and avoid create 2 ENeo4jNode objects.

Please let me know if this is possible.

Haiyangl

#6937 report it
Haensel at 2012/02/14 01:40pm
DataProviders

Regarding dataProviders: There is no specific dataProvider class out now for Neo4Yii so if you want to use CListView or CGridView etc. then you should use CArrayDataProvider(YourModel::findAll()). But take care: If you load more than let's say 100 models than this could be slow (also take into account that the simple traversals use "lazy loading").

greetings,

Haensel

#6935 report it
Haensel at 2012/02/14 11:56am
Indexing support

I just created a new branch on Github called "index-development" for all the indexing stuff. I hacked this together today so I don't want to merge it with the master branch yet. if you want to test it take a look at the ENeo4jGraphService class to get an idea of how to create indices and how to add/remove property containers. You can also query those indices via three new finder methods called findByExactIndexEntry(), findAllByExactIndexEntry() and findByIndexQuery(). Just look at ENeo4jNode/ENeo4jRelationship to get an idea on how to use them.

I know the documentation sucks, but the PHPdocs should give you a lot of information for now

Greetings,

Hannes/Haensel

#6922 report it
HLii at 2012/02/13 04:39pm
Thanks

Looking forward to it.

haiyangl

#6892 report it
Haensel at 2012/02/11 07:12am
Indexing nodes/relationships

Hi haiyangi,

Not yet, but I plan to add this feature next week or so. It will definitely be part of this extension

Greetings,

Haensel

#6878 report it
HLii at 2012/02/10 04:10pm
Index

Hi, Haensel,

Thank you for putting this together. I am still learning it. One question came up. Is there a way in Neo4Yii to explicit create index on a Neo4j data store?

Thanks

HLii

Leave a comment

Please to leave your comment.

Create extension
Downloads
No downloadable files yet