lphuberdeau / Neo4j-PHP-OGM

A doctrine2 style library to access neo4j graphs
156 stars 45 forks source link

findAll failing to fetch ManyToOne relationship #94

Closed RedactedProfile closed 9 years ago

RedactedProfile commented 9 years ago

I have a very simple schema right now. My database consists of exactly 5 nodes right now: 4 "User" nodes, and 1 "UserGroup" node. I am trying to craft a user editor at the moment. ALL Four User's are associated with the one UserGroup node (Which happens to be 'Admin' by name)

graph

I can see via the Row's view and all exports that each "Row" consists of the right user, and the same Admin UserGroup node.

However, when I use this libraries findAll method

$userRepo = $this->get('neo4j.manager')->getRepository('AppBundle\Entity\User');
$data = $userRepo->findAll();

The returned rows are weird.

The first element (User) has the group property with the Admin group Every element beyond the first, has no group property.

The only way I can get the group to show up, is by iterating through and forcing hydration:

foreach($data as $item) $item->getGroup();

^^^ That is not ideal, is there any possible way to force child hydration?

RedactedProfile commented 9 years ago

It's worth noting that when I use a custom repository to fetch the same data:

class UserRepository extends BaseRepository
{

    function findAllEx()
    {
        return $this->getEntityManager()->createCypherQuery()
            ->match('(User) -[:group]-> (UserGroup)')
            ->end('User,UserGroup')
            ->getList();
    }

When using this in my controller instead of the findAll() method, I get the exact same results as findAll().

lphuberdeau commented 9 years ago

There are currently no features to optimize hydration. In most scenarios, the few extra requests are not much of a cost. For the few cases where it is not fast enough, a custom query is the best way to go.

Contributions are welcome, although query optimizers tend to be hard to get right.

RedactedProfile commented 9 years ago

Hi Louis, thanks for the quick response

But the problem is that I did try a custom query (repo query) and the problem continues here.

This query is designed to handle thousands of users, and every single one of them has a group. Are we saying that I actually need to do a redundant loop through each result just to reliably get the data?

What I don't understand is why the first result has it, but the rest don't until I manually prod for it with this loop. With Doctrine I needed only to use a join in the query builder and the sub entity result would reliably show up in the results.

This, to me, makes the ManyToOne relationship system broken. The hydration modes don't really need to exist, that's fine, but when I use the cypher query builder in the entity repository and test the query in the neo browser for my expected row integrity (sure enough, it's all there) and the results with this OGMs mapper doesn't match up (and worse I need to stoop to additional sub routines to get what I need) I get a little nervous about using it for mission critical code. I haven't used the ManyToMany quite yet, if that possesses the same behaviours then we're talking even on pagination with users, thousands of queries per page based purely on a requirement needed for each user. So I'm definitely hoping not...

Sent from my iPhone

On Sep 22, 2015, at 5:11 AM, Louis-Philippe Huberdeau notifications@github.com wrote:

There are currently no features to optimize hydration. In most scenarios, the few extra requests are not much of a cost. For the few cases where it is not fast enough, a custom query is the best way to go.

Contributions are welcome, although query optimizers tend to be hard to get right.

— Reply to this email directly or view it on GitHub.

lphuberdeau commented 9 years ago

There is simply no hydration beyond what is done on-demand through the auto-generated proxy classes.

If you believe there is a bug, write a test to demonstrate it. Better yet, fix it in a PR.

RedactedProfile commented 9 years ago

I understand what your saying but what I'm getting at is the behaviour your talking about and the results I'm getting aren't matching up, I'm getting mixed results. If the first result simply didn't have the group property hydrated, I would have treated this as on purpose, but it does. Simply it's the rest of the results that don't that make it weird. Additionally when using a custom query to return the UserGroup with the results (which again, are apart of the result set this time) it's the exact same behaviours as the built in findAll

So yes I believe there is a big somewhere. Not with hydration but with mapping returned result sets.

I would gladly like to help fix this sure, but I nonetheless am unsure of which direction this is supposed to go. Shouldn't, if returned in a result set, that data be mapped? I get findAll being surface level with no hydration, in that sense it matches Doctrine. So why is one of the results hydrated?

This is what I'm getting at here, there's two scenarios that I'm being told should work in specific wAys, but neither do

  1. findAll shouldn't have any sub entities hydrated until on demand
  2. Cypher query should populate if part of a returned result set

No?

Sent from my iPhone

On Sep 22, 2015, at 7:59 AM, Louis-Philippe Huberdeau notifications@github.com wrote:

There is simply no hydration beyond what is done on-demand through the auto-generated proxy classes.

If you believe there is a bug, write a test to demonstrate it. Better yet, fix it in a PR.

— Reply to this email directly or view it on GitHub.