Retrive DateTime from Neo4j using Lumen and NeoEloquent OGM

142 Views Asked by At

Context

I'm creating an api rest that it interfaces to a graph db already filled by nodes and edge that describes events and exhibit's positions inside several museum that are charactirized by zones. In particular there are some edges between exhibits and zones that has properties like start time and coordinates. Start time is a property that is in according with DateTime neo4j format, below an example:

{
  "start": "2018-01-01T00:00:01.300Z",
  "coordinate": [
    0,
    0,
    0
  ]
}

The way that I follow to create the edge is:

CREATE (exhibit)-[:belongs_to {start:datetime('2018-01-01T00:00:01.300Z')}]->(zone)

where exhibit and zone are respectevly the nodes id.

Issue

I'd like to retrieve the start property from a specific edge but this is the result:

Unsupported property type: class java.time.ZonedDateTime

Code

findZone function generate the issue:

<?php

    namespace App;

    use Vinelab\NeoEloquent\Eloquent\Model;
    use App\Http\Controllers\ZoneController;

    class Exhibit extends Model{
        protected $label = 'Exhibit';

        protected $fillable = [];

        protected $hidden = [];

        public function zones(){
            return $this->belongsToMany('App\Zone', 'belongs_to');
        }

        public static function findZone($exhibit){
            $edge = $exhibit->zones()->edge(ZoneController::showZoneByName("Parlatorio"));

            return $edge->start;
        }
    }

I've try to give to edge only coordinates property and when I replace start property with coordinate the function work.

Stack Trace

Headers: Array
(
    [Date] =>  Mon, 15 Oct 2018 21:28:14 GMT
    [Access-Control-Allow-Origin] =>  *
    [Content-Type] =>  application/json; charset=UTF-8; stream=true
    [Content-Length] =>  6379
)
Body: Array
(
    [message] => Unsupported property type: class java.time.ZonedDateTime
    [exception] => IllegalArgumentException
    [fullname] => java.lang.IllegalArgumentException
    [stackTrace] => Array
        (
            [0] => org.neo4j.server.helpers.PropertyTypeDispatcher.dispatchOtherProperty(PropertyTypeDispatcher.java:246)
            [1] => org.neo4j.server.helpers.PropertyTypeDispatcher.dispatch(PropertyTypeDispatcher.java:95)
            [2] => org.neo4j.server.helpers.PropertyTypeDispatcher.consumeProperties(PropertyTypeDispatcher.java:51)
            [3] => org.neo4j.server.rest.repr.PropertiesRepresentation.serialize(PropertiesRepresentation.java:51)
            [4] => org.neo4j.server.rest.repr.RelationshipRepresentation.extraData(RelationshipRepresentation.java:127)
            [5] => org.neo4j.server.rest.repr.ObjectRepresentation.serialize(ObjectRepresentation.java:147)
            [6] => org.neo4j.server.rest.repr.MappingRepresentation.serialize(MappingRepresentation.java:41)
            [7] => org.neo4j.server.rest.repr.OutputFormat.lambda$stream$0(OutputFormat.java:183)
            [8] => org.neo4j.server.rest.dbms.AuthorizationEnabledFilter.doFilter(AuthorizationEnabledFilter.java:123)
            [9] => org.neo4j.server.rest.web.CorsFilter.doFilter(CorsFilter.java:115)
            [10] => org.neo4j.server.rest.web.CollectUserAgentFilter.doFilter(CollectUserAgentFilter.java:69)
            [11] => java.base/java.lang.Thread.run(Unknown Source)
        )

    [errors] => Array
        (
            [0] => Array
                (
                    [code] => Neo.DatabaseError.General.UnknownError
                    [message] => Unsupported property type: class java.time.ZonedDateTime
                    [stackTrace] => java.lang.IllegalArgumentException: Unsupported property type: class java.time.ZonedDateTime
\tat org.neo4j.server.helpers.PropertyTypeDispatcher.dispatchOtherProperty(PropertyTypeDispatcher.java:246)
\tat org.neo4j.server.helpers.PropertyTypeDispatcher.dispatch(PropertyTypeDispatcher.java:95)
\tat org.neo4j.server.helpers.PropertyTypeDispatcher.consumeProperties(PropertyTypeDispatcher.java:51)
\tat org.neo4j.server.rest.repr.PropertiesRepresentation.serialize(PropertiesRepresentation.java:51)
\tat org.neo4j.server.rest.repr.RelationshipRepresentation.extraData(RelationshipRepresentation.java:127)
\tat org.neo4j.server.rest.repr.ObjectRepresentation.serialize(ObjectRepresentation.java:147)
\tat org.neo4j.server.rest.repr.MappingRepresentation.serialize(MappingRepresentation.java:41)
\tat org.neo4j.server.rest.repr.OutputFormat.lambda$stream$0(OutputFormat.java:183)
\tat com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:71)
\tat com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:57)
\tat com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:302)
\tat com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1510)
\tat com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419)
\tat com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409)
\tat com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:409)
\tat com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:558)
\tat com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:733)
\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
\tat org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
\tat org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1655)
\tat org.neo4j.server.rest.dbms.AuthorizationEnabledFilter.doFilter(AuthorizationEnabledFilter.java:123)
\tat org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1642)
\tat org.neo4j.server.rest.web.CorsFilter.doFilter(CorsFilter.java:115)
\tat org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1642)
\tat org.neo4j.server.rest.web.CollectUserAgentFilter.doFilter(CollectUserAgentFilter.java:69)
\tat org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1642)
\tat org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
\tat org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
\tat org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
\tat org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
\tat org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1317)
\tat org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
\tat org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
\tat org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
\tat org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
\tat org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1219)
\tat org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
\tat org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:61)
\tat org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
\tat org.eclipse.jetty.server.Server.handle(Server.java:531)
\tat org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:352)
\tat org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
\tat org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281)
\tat org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
\tat org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
\tat org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
\tat org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
\tat org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
\tat org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
\tat org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
\tat org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:762)
\tat org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:680)
\tat java.base/java.lang.Thread.run(Unknown Source)

                )

        )

)
at E:\\laravel-projects\\api_certose\\vendor\\heydavid713\
eo4jphp\\lib\\Everyman\\Neo4j\\Command.php:116)
[stacktrace]
#0 E:\\laravel-projects\\api_certose\\vendor\\heydavid713\
eo4jphp\\lib\\Everyman\\Neo4j\\Command\\GetRelationship.php(78): Everyman\\Neo4j\\Command->throwException('Unable to retri...', 500, Array, Array)
#1 E:\\laravel-projects\\api_certose\\vendor\\heydavid713\
eo4jphp\\lib\\Everyman\\Neo4j\\Command.php(69): Everyman\\Neo4j\\Command\\GetRelationship->handleResult(500, Array, Array)
#2 E:\\laravel-projects\\api_certose\\vendor\\heydavid713\
eo4jphp\\lib\\Everyman\\Neo4j\\Client.php(828): Everyman\\Neo4j\\Command->execute()
#3 E:\\laravel-projects\\api_certose\\vendor\\heydavid713\
eo4jphp\\lib\\Everyman\\Neo4j\\Client.php(544): Everyman\\Neo4j\\Client->runCommand(Object(Everyman\\Neo4j\\Command\\GetRelationship))
#4 E:\\laravel-projects\\api_certose\\vendor\\heydavid713\
eo4jphp\\lib\\Everyman\\Neo4j\\Relationship.php(102): Everyman\\Neo4j\\Client->loadRelationship(Object(Everyman\\Neo4j\\Relationship))
#5 E:\\laravel-projects\\api_certose\\vendor\\heydavid713\
eo4jphp\\lib\\Everyman\\Neo4j\\PropertyContainer.php(235): Everyman\\Neo4j\\Relationship->load()
#6 E:\\laravel-projects\\api_certose\\vendor\\heydavid713\
eo4jphp\\lib\\Everyman\\Neo4j\\Relationship.php(78): Everyman\\Neo4j\\PropertyContainer->loadProperties()
#7 E:\\laravel-projects\\api_certose\\vendor\\vinelab\
eoeloquent\\src\\Eloquent\\Edges\\Finder.php(144): Everyman\\Neo4j\\Relationship->getStartNode()
#8 E:\\laravel-projects\\api_certose\\vendor\\vinelab\
eoeloquent\\src\\Eloquent\\Edges\\Finder.php(171): Vinelab\\NeoEloquent\\Eloquent\\Edges\\Finder->directionFromRelation(Object(Everyman\\Neo4j\\Relationship), Object(App\\Exhibit), Object(App\\Zone))
#9 E:\\laravel-projects\\api_certose\\vendor\\vinelab\
eoeloquent\\src\\Eloquent\\Edges\\Finder.php(80): Vinelab\\NeoEloquent\\Eloquent\\Edges\\Finder->edgeFromRelationWithDirection(Object(Everyman\\Neo4j\\Relationship), Object(App\\Exhibit), Object(App\\Zone), 'any')
#10 E:\\laravel-projects\\api_certose\\vendor\\vinelab\
eoeloquent\\src\\Eloquent\\Relations\\BelongsToMany.php(158): Vinelab\\NeoEloquent\\Eloquent\\Edges\\Finder->first(Object(App\\Exhibit), Object(App\\Zone), 'belongs_to')
#11 E:\\laravel-projects\\api_certose\\app\\Exhibit.php(20): Vinelab\\NeoEloquent\\Eloquent\\Relations\\BelongsToMany->edge(Object(App\\Zone))
#12 E:\\laravel-projects\\api_certose\\app\\Http\\Controllers\\ExhibitController.php(44): App\\Exhibit::findZone(Object(App\\Exhibit))
#13 [internal function]: App\\Http\\Controllers\\ExhibitController->retrieveZone('187')
#14 E:\\laravel-projects\\api_certose\\vendor\\illuminate\\container\\BoundMethod.php(29): call_user_func_array(Array, Array)
#15 E:\\laravel-projects\\api_certose\\vendor\\illuminate\\container\\BoundMethod.php(87): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#16 E:\\laravel-projects\\api_certose\\vendor\\illuminate\\container\\BoundMethod.php(31): Illuminate\\Container\\BoundMethod::callBoundMethod(Object(Laravel\\Lumen\\Application), Array, Object(Closure))
#17 E:\\laravel-projects\\api_certose\\vendor\\illuminate\\container\\Container.php(564): Illuminate\\Container\\BoundMethod::call(Object(Laravel\\Lumen\\Application), Array, Array, NULL)
#18 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(373): Illuminate\\Container\\Container->call(Array, Array)
#19 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(339): Laravel\\Lumen\\Application->callControllerCallable(Array, Array)
#20 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(313): Laravel\\Lumen\\Application->callLumenController(Object(App\\Http\\Controllers\\ExhibitController), 'retrieveZone', Array)
#21 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(275): Laravel\\Lumen\\Application->callControllerAction(Array)
#22 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(260): Laravel\\Lumen\\Application->callActionOnArrayBasedRoute(Array)
#23 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(230): Laravel\\Lumen\\Application->handleFoundRoute(Array)
#24 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(164): Laravel\\Lumen\\Application->handleDispatcherResponse(Array)
#25 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(413): Laravel\\Lumen\\Application->Laravel\\Lumen\\Concerns\\{closure}()
#26 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(166): Laravel\\Lumen\\Application->sendThroughPipeline(Array, Object(Closure))
#27 E:\\laravel-projects\\api_certose\\vendor\\laravel\\lumen-framework\\src\\Concerns\\RoutesRequests.php(107): Laravel\\Lumen\\Application->dispatch(NULL)
#28 E:\\laravel-projects\\api_certose\\public\\index.php(28): Laravel\\Lumen\\Application->run()
#29 {main}
"} 
2

There are 2 best solutions below

2
On BEST ANSWER

I also encountered the issue and have not been able to find a way around this in the way that you want. It is in the neoeloquent library itself as far as I can figure out. However I have come up with an alternative which is not ideal since it would be better to be able to do it with the library but it works.

I have written a RawQueryService which can take a raw Neo4j query and retrieve the output as an associative array.

The RawQueryService is as follows:

<?php

namespace App\Services;

use Illuminate\Support\Facades\DB;

class RawQueryService
{

    public static function executeRawQuery(string $query, $noProcessing=false) {
        $result = DB::select($query);

        $resultArray = array();
        foreach($result as $row){
            $result = $row['n'];
            array_push($resultArray, $result);
        }

        return $resultArray;
    }


}

And then to retrieve the start time:

$start = \App\Services\RawQueryService::executeRawQuery(
         "match(n) where n.title=\"".$title."\" return toString(n.start)");

It converts the datetime internally to a string so the Neo4j library does not receive an IllegalArgumentException.

I hope this helps you.

0
On

I've been grappling this issue, and found that there is a problem with serializing datetime properties in the server REST API. There are a few different errors generated depending on http vs bolt and the query type, but they disappear when datetime properties are removed from the response.

v3.5.0 of the server fixes it for HTTP requests. I haven't validated bolt on this version.

Some more details of my investigation and resolution are at https://github.com/neo4jrb/neo4j/issues/1522 (ruby gem client). The problem exists in both v3.4.1 and 3.4.6.