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 ¶
Download my ActiveResource extension and add it to your extensions folder (If you haven't done already).
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
*/
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
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
Thanks
Looking forward to it.
haiyangl
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
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
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
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
Thanks
I will open a ticket in GitHub.
haiyangl
Remove relationship in neo4j
How to remove relationship in neo4j? Please help.
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
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.