Code Monkey home page Code Monkey logo

Comments (6)

sts85 avatar sts85 commented on June 15, 2024

I implemented a hotfix that works for my current setup. I have a mappedBy annotation defined on all relationships with relationship entities.

Code to be inserted in GraphAware\Neo4j\OGM\Hydrator\EntityHydrator right after

$targetEntity = $otherHydrator->hydrateNode($targetNode);

First determine what is start node and what is end node

        /*
         * Bugfix:
         * If Relationship Entity start node and end node are of the same class, determine the start node
         * and end node based on the mapping given in the annotation
         */
        $startNodeIsSourceEntity = false;
        if ($relationshipEntityMetadata->getStartNodeClass() == $relationshipEntityMetadata->getEndNodeClass()) {

            if (!$relationshipMetadata->getMappedByProperty()) {
                throw new \Exception('Invalid RelationshipEntity annotations. You need to define a mappedBy'
                    . ' annotation if startNode and endNode in a RelationshipEntity are of the same class');
            }

            if ($relationshipMetadata->getDirection() == Direction::OUTGOING) {
                $startNodeIsSourceEntity = true;
            } else {
                $startNodeIsSourceEntity = false;
            }
            // TODO: BOTH

        } else if ($relationshipEntityMetadata->getStartNodeClass() === $this->_classMetadata->getClassName()) {
            $startNodeIsSourceEntity = true;
        }

And then adjust the ste start node and set end node conditions

        // set the start node
        #if ($relationshipEntityMetadata->getStartNodeClass() === $this->_classMetadata->getClassName()) {
        if ($startNodeIsSourceEntity) {
            $relationshipEntityMetadata->setStartNodeProperty($entity, $sourceEntity);
        } else {
            $relationshipEntityMetadata->setStartNodeProperty($entity, $targetEntity);
        }

        // set the end node
        #if ($relationshipEntityMetadata->getEndNodeClass() === $this->_classMetadata->getClassName()) {
        if (!$startNodeIsSourceEntity) {
            $relationshipEntityMetadata->setEndNodeProperty($entity, $sourceEntity);
        } else {
            $relationshipEntityMetadata->setEndNodeProperty($entity, $targetEntity);
        }

This works only for INCOMING and OUTGOING directions, not for directions marked with BOTH

from neo4j-php-ogm.

sts85 avatar sts85 commented on June 15, 2024

There is another issue on n:m relationships with RelationshipEntities.

        // guess the name of the property on the other node
        foreach ($otherMetadata->getRelationships() as $rel) {
            if ($rel->isRelationshipEntity()
                && $rel->getRelationshipEntityClass() === $relationshipEntityMetadata->getClassName()
                ) {
                if (!$rel->isCollection()) {
                    $rel->setValue($targetEntity, $entity);
                } else {
                    $rel->initializeCollection($targetEntity);
                    $rel->addToCollection($targetEntity, $entity);
                }
            }
        }

The line $rel->addToCollection($targetEntity, $entity); adds the entity to the inverse side of the collection, but the inverse side is not initialized correctly (proxy stays on not initialized). This results in entities getting added twice to the ArrayCollection as soon as they are read on the inverse side (the initialize method is then called and the result set is added to the array collection).

Sorry, I am quite busy right now so I can't really look into it now. Uncommenting this line works for now. The effect is that more queries need to be send to the database, but on the other hand the results are correct.

I will try to come with concrete test cases, but this will take a few weeks.

from neo4j-php-ogm.

sts85 avatar sts85 commented on June 15, 2024

And in General: Determining the other side of the relationship by guessing the class name will result in quite some issues in any case where 2 Entities are related more than one time. E.g., (:User)-[:LIKES {since: 123}]->(:Company) and (:User)-[:VISITED {onDate: 123}]->(:Company).

from neo4j-php-ogm.

ikwattro avatar ikwattro commented on June 15, 2024

Thanks @sts85 , for this part :

The line $rel->addToCollection($targetEntity, $entity); adds the entity to the inverse side of the collection, but the inverse side is not initialized correctly (proxy stays on not initialized). This results in entities getting added twice to the ArrayCollection as soon as they are read on the inverse side (the initialize method is then called and the result set is added to the array collection).

This is fixed by #108 .

I will look at the other issue.

from neo4j-php-ogm.

sts85 avatar sts85 commented on June 15, 2024

Hi,

I just updated my dev environment to RC6 (I was still working on RC3 with my hotfix).

But RC-6 still does not work with my model.

Commenting out these lines of code in EntityHydrator

        // TODO: HOTFIX by sts - does not work properly
//            $startNodePropertyName = $relationshipEntityMetadata->getStartNodePropertyName();
//            $sourceEntityMappedName = $relationshipMetadata->getMappedByProperty();
//
//            $startNodeIsSourceEntity = $startNodePropertyName === $sourceEntityMappedName;

And using these lines

/*
         * 
         * Eliminate error described in https://github.com/graphaware/neo4j-php-ogm/issues/106
         * If Relationship Entity start node and end node are of the same class, determine the start node
         * and end node based on the mapping given in the annotation
         */
        $startNodeIsSourceEntity = false;
        if ($relationshipEntityMetadata->getStartNodeClass() == $relationshipEntityMetadata->getEndNodeClass()) {

            if (!$relationshipMetadata->getMappedByProperty()) {
                throw new \Exception('Invalid Relationship Entity annotations. You need to define a mappedBy'
                    . ' annotation if startNode and endNode in a RelationshipEntity are of the same class');
            }

            if ($relationshipMetadata->getDirection() == Direction::OUTGOING) {
                $startNodeIsSourceEntity = true;
            } else if ($relationshipMetadata->getDirection() == Direction::INCOMING) {
                $startNodeIsSourceEntity = false;
            } else {
                throw new \Exception('Invalid Relationship Entity annotations. Direction BOTH not supported on'
                    . 'RelationshipEntities where startNode and endNode are of the same class');
            }
            // TODO: BOTH

        } else if ($relationshipEntityMetadata->getStartNodeClass() === $this->_classMetadata->getClassName()) {
            $startNodeIsSourceEntity = true;
        }

Makes it work again. I will look into this issue in a while, for now I will continue with the hotfix.

from neo4j-php-ogm.

cebe avatar cebe commented on June 15, 2024

The issue still exists, the test added with the fix does not verify the records assigned inside of the relation. Will send a PR with adjusted test to reproduce the issue.

from neo4j-php-ogm.

Related Issues (20)

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.