Code Monkey home page Code Monkey logo

neo4jphp's Introduction

Neo4jPHP

Author: Josh Adell [email protected]
Copyright (c) 2011-2012

PHP Wrapper for the Neo4j graph database REST interface

In-depth documentation and examples: http://github.com/jadell/neo4jphp/wiki

API documentation: http://jadell.github.com/neo4jphp

Build Status

Install

Using Composer

  1. From the command line composer require "everyman/neo4jphp" "dev-master"
  2. In your PHP script require("vendor/autoload.php");

Connection Test

Create a script named neo4jphp_connect_test.php:

    <?php
    require('vendor/autoload.php');
    
    $client = new Everyman\Neo4j\Client('localhost', 7474);
    print_r($client->getServerInfo());

Change localhost or 7474 to the host name and port of your Neo4j instance.

Execute the script:

> php neo4jphp_connect_test.php

If you see your server's information, then you have successfully connected!

Get Started

Full documentation on all the features of Neo4jPHP is available on the wiki: https://github.com/jadell/neo4jphp/wiki

Contributions

http://github.com/jadell/neo4jphp/graphs/contributors

All contributions are welcome! If you wish to contribute, please read the following guidelines:

  • Before implementing new features, open an issue describing the feature.
  • Include unit tests for any bug fixes or new features.
  • Include only one bug fix or new feature per pull request.
  • Make sure all unit tests run before submitting a pull request.
  • Follow the coding style of the existing code: tabs for indentation, class/method braces on newlines, spaces after commas, etc.
  • Contributing code means that you agree that any contributed code, documentation, or other artifacts may be released under the same license as the rest of the library.

Quick Contributor Setup

Install the developer tools:

> composer install --dev

After making your changes, run the unit tests and code style checker:

> vendor/bin/phing ci

Run only unit tests:

> vendor/bin/phing test

Run only style checker:

> vendor/bin/phing cs

Pull requests will not be accepted unless all tests pass and all code meets the existing style guidelines.

Special Thanks

Changes

0.1.0

  • Cypher and Gremlin results handle nested arrays of nodes/relationships
  • Batch request with no operations succeeds
  • Delete index where index does not exist succeeds

0.0.7-beta

  • Retrieve reference node in one operation
  • Find and return only the first matching relationship
  • Optionally use HTTPS and basic authentication
  • Keep index configuration when retrieved from server
  • Add Memcache caching plugin
  • Do not allow use if cUrl is not detected
  • PHAR is uncompressed by default

0.0.6-beta

  • Create full-text indexes; easier instantiation of common index types
  • Client can be initialized with a string and port instead of a Transport object
  • Setting a null property has the same effect as removing the property
  • Handle scalar values from Gremlin scripts properly
  • Cypher and Gremlin queries can take an array of named parameters
  • Cypher no longer uses positional parameters
  • Use server info to determine Cypher plugin endpoint

0.0.5-beta

  • Open a batch on the client to apply to all subsequent data manipulation calls
  • Batch operations correctly set and update locally cached entities
  • Method chaining on node and relationship save, load and delete
  • Instantiate new nodes and relationships from the client
  • Change to cache initialization; new EntityCache object

0.0.4-beta

  • Client::getServerInfo() retrieves server information and connection test
  • Add to index brought up to Neo4j server 1.5 specification
  • Return paths from Cypher queries
  • Properly encode URL entities
  • Connection and transport errors throw exceptions
  • Fix "unable to connect" bug from returning false positive

neo4jphp's People

Contributors

alexbilbie avatar chrisramakers avatar codingjoe avatar cosmologist avatar flip111 avatar huafu avatar jadell avatar jakewins avatar kevinc13 avatar lphuberdeau avatar mavimo avatar mitom avatar rado-h avatar tinsley avatar tolry avatar wwwdata avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

neo4jphp's Issues

Create a client without passing in a Transport

$client = new Client();
Should create its own Transport, using default settings.

Likewise:
$client = new Client('somehost', 7475);
Should create its own Transport, using the supplied host/port

Namespacing in wiki

Standardize use of namespacing throughout the wiki. If class aliases continue to be used, make mention of the namespace on the "getting started" page and anywhere aliased classes are used.

Checking if server is online

I think it would be good if it is able to check if the server is up before creating the client.. I did some modifications on my own..

Placed in transport

/**
*Check if server is online
*/
public function isOnline()
{
$holder = $this->makeRequest(self::GET, $this->path);
return $holder['code'];
}

Placed in Client

public function __construct(Transport $transport)
{
if($transport->isOnline())
$this->setTransport($transport);
else
exit("Neo4j server is offline");
}

this would ensure that the server is online before allowing anything else to take place, unfortunately its now relying on the error code 0 or 404. i am not very sure of the rest interface to get a proper one. Perhaps u could tell me O o

Batch Commit Fails when property value contains '\'

Due to how Neo4J handles batch processing the escape sequence needed for '' is awkward. Currently, any batch commit which contains a property value that contains a '' fails with an invalid argument exception. Removing the '' from the value seems to make it work ok but is a terrible solution. The only solution I've been able to find so far is:

In Everyman\Neo4j\Transport.php

$encoded = json_encode($data);
$encoded = str_replace('\\\\', '\\\\\\\\', $encoded);
return $encoded;

The downfall is this issue only happens during a batch commit, so the encoding fix only needs to occur on batch related data. We currently only commit in batches so we are good to go, but a better work around should probably be implemented.

Otherwise, fantastic library.

Unable to include Traversal.php

I installed neo4jphp on my local machine (Mac OS X 10.6 with MAMP) by adding

require("phar://neo4jphp.phar");

as described. Creating nodes and relationships works like a charme. But I am unable to create Traversals. I always run into the following error:

include(Traversal.php) [function.include]: failed to open stream: No such file or directory. I tried to include the file separately, but it does not help.

Any ideas?

Handle bad requests differently than not found

404 style errors should be handled by returning null or false where appropriate.

Other errors should be handled by throwing exceptions.

Also, don't count 0 as a valid response code; should translate to 500 unknown error

[Wiki] Nodes-and-Relationships.md

The call to Client::getId() will return a Node object if the Node was found successfully or null if not.

should be changed to

The call to Client::getNode() will return a Node object if the Node was found successfully or null if not.

Https and http basic auth

Allow users to configure a transport to use https and provide a username/password for http basic authentication.

Batch Branch: 400 Bad Request

Hi Josh,

I'm currently trying your batch branch and have encountered an error in committing operations, the following example code should work:

<?php
    use Everyman\Neo4j\Transport,
        Everyman\Neo4j\Client,
        Everyman\Neo4j\Index,
        Everyman\Neo4j\Relationship,
        Everyman\Neo4j\Node,
        Everyman\Neo4j\Batch;

    error_reporting(-1);
    ini_set('display_errors', 1);

    function loaderTestAutoloader($sClass)
    {
        $sLibPath = __DIR__.'/batch-lib/';
        $sClassFile = str_replace('\\',DIRECTORY_SEPARATOR,$sClass).'.php';
        $sClassPath = $sLibPath.$sClassFile;
        if (file_exists($sClassPath)) {
            require($sClassPath);
        }
    }
    spl_autoload_register('loaderTestAutoloader');

    $transport = new Transport();
    $client = new Client($transport);

    $batch = new Batch($client);

    $node = new Node($client);
    $node->setProperties(array('foo' => 'bar', 'baz' => 'qux'));
    $batch->save($node);

    $result = $batch->commit();
    var_dump($result);
?>

The issue lies in that $result will always return false. After some debugging I discovered that Java is returning a 400 Bad Request with the following message: java.util.LinkedHashMap cannot be cast to java.util.List in Transport->makeRequest(). The full stacktrace is available here: https://gist.github.com/25fd7f7aef3fdb77e32a

I'm currently running Neo4j 1.4.1 (upgraded from 1.4, just in case that was the problem).

Any ideas?

Cheers,

  • Peter

COLLECT() in Cypher queries returns arrays instead of nodes

Example:

$qryObj = new \Everyman\Neo4j\Cypher\Query($client, 'START n=node(0) MATCH (n)<--(x) RETURN n, collect(x) as a');
$data = $qryObj->getResultSet();
$stuff = $data[0];

$n = $stuff['n'];
$a = $stuff['a'];

var_dump($n); //object(Everyman\Neo4j\Node)
var_dump($a[0]); //array

It seems arrays of nodes in the restult are not recognized properly. This is probably true for relations as well, but I haven't tested it.
$a[0] = $client->getEntityMapper()->getEntityFor($a[0]) can be used as a workaround

Transparent batches

Allow batches to be opened and committed transparently. Example:

$batch = $client->startBatch();
// None of the following operations are sent to the server until...
$nodeA->save();
$nodeB->save();
$nodeA->relateTo($nodeB, 'KNOWS')->save();
$nameIndex->add($nodeB, 'name', 'foo');
// ...now
$client->commitBatch();
// or
$batch->commit();

Maybe in the future, all data operations will be wrapped in an implicit batch?

Add To Index exception

Tested on examples/directions.php
Neo4J version neo4j-community-1.4.M05

string(194) "Unsupported value type class java.util.LinkedHashMap. Supported value types are all java primitives (byte, char, short, int, long, float, double) and String, as well as arrays of all those types"
["exception"]=>
string(244) "org.neo4j.server.rest.web.PropertyValueException: Unsupported value type class java.util.LinkedHashMap. Supported value types are all java primitives (byte, char, short, int, long, float, double) and String, as well as arrays of all those types"
["stacktrace"]=>
array(38) {
[0]=>
string(88) "org.neo4j.server.rest.domain.JsonHelper.assertSupportedPropertyValue(JsonHelper.java:87)"
[1]=>
string(77) "org.neo4j.server.rest.domain.JsonHelper.jsonToSingleValue(JsonHelper.java:65)"

Failure to create large number of nodes

The following script repeatedly creates nodes and relationships. Around iteration 10000 (on my machine), an exception is thrown saying:

PHP Everyman\Neo4j\Exception: No relationship start node specified in /home/kratib/www/recotype/sites/all/libraries/Neo4jPHP/lib/Everyman/Neo4j/Command/CreateRelationship.php on line 76

Dumping the parameters of Everyman\Neo4j\Command\CreateNode::handleResult() shows they're all empty.

My environment:

  • Ubuntu 11.04
  • PHP 5.3, memory_limit = -1
  • Neo4j 1.4.1
#!/usr/bin/env php
<?php
use Everyman\Neo4j\Transport,
  Everyman\Neo4j\Client,
  Everyman\Neo4j\Index,
  Everyman\Neo4j\Relationship,
  Everyman\Neo4j\Node;
error_reporting(-1);
ini_set('display_errors', 1);

function loaderTestAutoloader($sClass)
{
  $sLibPath = __DIR__.'/../lib/';
  $sClassFile = str_replace('\\',DIRECTORY_SEPARATOR,$sClass).'.php';
  $sClassPath = $sLibPath.$sClassFile;
  if (file_exists($sClassPath)) {
    require($sClassPath);
  }
}
spl_autoload_register('loaderTestAutoloader');

$transport = new Transport();
$client = new Client($transport);

for ($i = 1; $i<=500000; ++$i) {
  $node = new Node($client);
  $node->setProperty('status_id', $i)->save();
  $user = new Node($client);
  $user->setProperty('user_id', $i)->save();
  try {
    $user->relateTo($node, 'TEST')->save();
  }
  catch (Exception $e) {
    echo $e->getMessage() . "\n";
  }
  if ($i % 100 == 0) {
    echo "$i\n";
  }
}

Traversal setPruneEvaluator doesn't work

In the example

$traversal = new Traversal($client);
$traversal->setPruneEvaluator(Traversal::PruneNone)
    ->setReturnFilter('javascript', 'return true;')
    ->setOrder(Traversal::OrderBreadthFirst);

chaining will not work because setPruneEvaluator() doesn't return the object. Moreover the properties of prune are "language" and "name" not "language" and "body" so in this case setPruneEvaluator should set
"prune_evaluator" : {"name" : "none","language" : "builtin"}
instead of
"prune_evaluator" : {"body" : "none","language" : "builtin"}

Setup is not exactly straightforward

The most likely cause of this is my total ignorance of PHP Namespaces, but when I followed the instructions and did the following:

include("neo4jphp.phar");

...

I got the following error:

Fatal error: Class 'Everyman\Neo4j\Client' not found in XXX.php on line YYY

After this, I tried to stick the source-code in a folder called lib in the root of my project, and the following code works perfectly:

<?php

    spl_autoload_register("autoload");

    use Everyman\Neo4j\Client,
        Everyman\Neo4j\Transport;

    $client = new Client(new Transport('localhost', 7474));
    print_r($client->getServerInfo());

    function autoload($file)
    {
        $base = dirname(__FILE__)."/lib";
        $filename = str_replace('\\', DIRECTORY_SEPARATOR, $file) . '.php';
        if(file_exists($base.DIRECTORY_SEPARATOR.$filename))
            require_once($base.DIRECTORY_SEPARATOR.$filename);
    }

?>

I think it might be a far smaller barrier to entry if you were to include an example like this in your wiki - that is, if I didn't totally miss something fundamental with the phar example.

Browser vs. Terminal

Hello,

Neo4JPHP is working properly on my terminal (Ubuntu 12.04) but it seems I cannot achieve to run the same php file on my browser. Everything else is also working properly on my browser but when any connection via Neo4JPHP returns me a HTTP Error 500.

I'm using phar package and even the code below crashes on browser:

require( "phar://neo4jphp.phar");
$client = new Everyman\Neo4j\Client();
$client->getTransport();

I cannot give any more details, what should it be caused from?

Batch operations do not remove unsaved node

Batch operations do not handle removing unsaved nodes from an index. This is appropriate to do if the node is saved in a prior batch operation. Helps ensure uniqueness in an index. Should work the same as adding an unsaved node to an index.

Warnings with ExecuteGremlinQuery

Gremlin scripts may return other types than array.

For instance, executing g.v(1).name will return

Warning: array_key_exists() expects parameter 2 to be array, string given in /Users/Pierre/Sites/EC2/survey/lib/Everyman/Neo4j/Command/ExecuteGremlinQuery.php on line 89

Warning: Invalid argument supplied for foreach() in /Users/Pierre/Sites/EC2/survey/lib/Everyman/Neo4j/Command/ExecuteGremlinQuery.php on line 92

To prevent those warnings, a check may be added on top of Command/ExecuteGremlinQuery.php:

if (!is_array($data)) {
    $data = array($data);
}

When iterating through ResultSet, you may use f.i. is_object($row[0]) to check what Gremlin returns.

Hope that makes sense for you,
Pierre

Typo in the wiki

The line ./bacon.php "Keanu Reeves" "Kevin Bacon" should be ./bacon.php path "Keanu Reeves" "Kevin Bacon".

After two years of using Github daily, I still don't know how I can contribute to wikis on repos :-)

Automatic pagination

As Neo4j server has difficulty responding with large data sets, it might make sense to automatically and transparently paginate the results of Cypher (and Gremlin?) queries if explicit SKIP/LIMIT pagination is not set.

Support for Memcache (no d)

I just finished making a memcache caching plugin. By make I mean I changed line 64 of the Memcached plugin to

return $this->memcached->set($key, $value, 0, $expire);

That's the only difference as far as I can tell and it has been working fine for me so far.

I'm using a Windows server so this small addition saved me the from trying to compile the memcached extension myself.

Batch/Sequential Insert Benchmarks

Josh,

I'm opening a separate ticket for this as it's not related to #4. I'm running the batch operations using the following example script:
https://gist.github.com/9ca60c4b021168af33aa

This yields the following benchmarks:

Created 10000 nodes via batch took: 5.60 minutes.
Created 10000 nodes sequentially took: 27 seconds.

I thought that perhaps it's related to my memory configuration, so I increased them based on what Neo4j recommend (http://wiki.neo4j.org/content/Batch_Insert), but it had little to no effect on the above stats.

This may not be a Neo4PHP issue, as Neo4j do state that batch insertions are experimental, but thought it'd be worth flagging!

Cheers,

  • Peter

Empty batch exception

Example code:

$client = new Everyman\Neo4j\Client();
$client->startBatch();
// ..
// some code which not executed (if condition for example)
// ..
$client->commitBatch();

throws "PHP Fatal error: Uncaught exception 'Everyman\Neo4j\Exception' with message 'Unable to commit batch [500]:"

I think it is a good idea to allow to make empty batch which does nothing.

Loading edge start and end node properties

About a month ago whenever I searched for an edge node [ getRelationship( $id ) ], both the start and end nodes, along with the edge node properties were loaded. Now, after the last changes, only the edge node properties are there, the start and end nodes must be explicitly loaded [ load() ] to access their properties.

I also noticed that the "lazyLoad" protected property is on for start and end nodes, but off for the edge node: I am new to Neo4j-PHP so I don't really know how and if this property is used, but I suspect it may have to do with this issue.

Is there a fix for this or what is the default workflow when getting nodes and edges?

Thanks!

Milko

Undefined offset (GetServerInfo::parseVersion)

PHP Notice: Undefined offset: 2 in phar:///neo4jphp.phar/lib/Everyman/Neo4j/Command/GetServerInfo.php on line 72

This is GetServerInfo::parseVersion method and $fullVersion variable is "1.5".

get exception in batch with string " and \

// php code
$client = new Client(new Transport());
$batch = new Batch($client);
$index = new Index($client, Index::TypeNode, 'index_test');

$name = 'string \ and "test"';
// escape part
//$name = str_replace('\', '\\', $name);
//$name = str_replace('"', '"', $name);

$node = new Node($client);
$node->setProperty('NAME', $name);
$batch->save($node);

//$batch->addToIndex($index, $node, 'NAME', $node->getProperty('NAME'));
$batch->commit();
//end of code

if there are \ or " string in property of node or value of index, i got exception.
the request of commit will be like this below and it get error.
post /db/data/batch[{"method":"POST","to":"/node","body":{"NAME":"string\ and "test""},"id":0}]

then i uncomment the escape part of code, the result of request will be like this:
post /db/data/batch[{"method":"POST","to":"/node","body":{"NAME":"string\\ and \"test\""},"id":0}]
this runs well.

But it runs correctly when i use $node->save() what ever what string it is.
Only get error with batch.
i'm not sure if this is a problem of php or server of neo4j.

i'm using Neo4j 1.5.M02, and tested on both of 0.0.4-beta and 0.0.5-beta.

Annotations and auto-entities

Start looking at annotations, possibly following the Spring Data Graph syntax. Look to Doctrine2 for inspiration.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.