floriansemm / SolrBundle

Solr-Integration into Symfony and Doctrine2
http://floriansemm.github.io/SolrBundle
MIT License
123 stars 73 forks source link

Multivalues problem #130

Closed hanzx closed 8 years ago

hanzx commented 8 years ago

Hello, i have a problem. Solrbundle response not return data for keys [ca,cai and other multivalues]. Thanks.

Query:

   $query = $this->get('solr.client')->createQuery('AppBundle:Solr\Product');
     $query->setHydrationMode(HydrationModes::HYDRATE_DOCTRINE);
        $query->addSearchTerm('id', '0000284-34');
        $result = $result = $query->getResult();

Solr response

{
  "response": {
    "numFound": 1,
    "start": 0,
    "docs": [
      {
        "id": "0000284-34",
        "m": "",
        "p": "Golfový kočárek 4Baby Rio 2015 Red",
        "p2": "Golfový kočárek 4Baby Rio 2015 Red",
        "ca": [
          "Kočárky"
        ],
        "cai": [
          1310,
          1749
        ],
        "c": "0000284",
        "cn": "eAndilek.cz",
        "zip": "73601",
        "re": 1006,
        "gen": 703,
        "sr": [
          1528,
          1529
        ]
      }
    ]
  }
}

Solr bundle response:

array:1 [▼
  0 => Product {#1318 ▼
    -id: "0000284-34"
    -p: "Golfový kočárek 4Baby Rio 2015 Red"
    -p2: "Golfový kočárek 4Baby Rio 2015 Red"
    -u: "http://www.eandilek.cz/golfovy-kocarek-4baby-rio-2015-red/"
    -iu: "http://www.eandilek.cz/img/galery/default/1_131858.jpg"
    -vu: ""
    -e: ""
    -i: ""
    -pn: ""
    -ca: null
    -cai: null
    -acai: null
    -c: "0000284"
    -pr: 1329.0
    -pv: 1329.0
    -m: ""
    -d: "Golfový kočárek 4Baby Rio 2013 v nové atraktivní kolekci je určen pro děti od 12 měsíců do cca 3-4 let (max. do 15 kg)."
    -dei: 14
    -cn: "eAndilek.cz"
    -zip: "73601"
    -re: 1006
    -sta: null
    -gen: 703
    -sr: null
    -rnd: null
    -del: null
    -pp: null
    -qi: 5
    -qs: "imitcapa"
    -gk: "1dd1803606747fcd8fe6965f9797edcf"
    -gift: ""
    -igid: "9448"
    -acc: null
  }
]
floriansemm commented 8 years ago

can you provide your solr-mapping?

hanzx commented 8 years ago

For ca key :

 /**
     * Category names
     * @var Category[]
     *
     * @Solr\Field(name="ca", type="strings", getter="getName")
     * @ORM\OneToMany(targetEntity="ArtikulBundle\Entity\Solr\Category", mappedBy="categories", cascade={"persist"})
     *
     */
    private $ca;

Category:

class Category
{
    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }
}
floriansemm commented 8 years ago

Your mapping looks good. Maybe your data is inconsistent and the doctrine-hydrator can't find the target entity. Make sure your relation between Product and Category is persisted properly.

hanzx commented 8 years ago

when I use command "doctrine:schema:update --force" ->

[Doctrine\ORM\Mapping\MappingException]                                      
  Class "ArtikulBundle\Entity\Solr\Category" is not a valid entity or mapped   
  super class.    

It works only when I add annotations to class (/**

In your example is class without annotations.

class Tag
{
    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }
}

Have you some your code for inspiration ?

floriansemm commented 8 years ago

You configure with @ORM\OneToMany(targetEntity="ArtikulBundle\Entity\Solr\Category", mappedBy="categories", cascade={"persist"}) a db-relation to Category, this means Category must be an entity too.

see http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-many-bidirectional

hanzx commented 8 years ago

I have

* Class Category
 * @package ArtikulBundle\Entity\Solr
 *
 * @ORM\Entity
 * @ORM\Table(name="category")
 */
class Category
{
    /**
     * @var
     *
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\ManyToOne(targetEntity="ArtikulBundle\Entity\Solr\Product",inversedBy="ca")
     *
     */

still return empty ca,


  -ca: ArrayCollection {#599 ▼
      -elements: []
    } 
hanzx commented 8 years ago

function hydrate in ValueHydrator class, variable $document contain my key 'ca' = $property with $value ['name1','name2'] and function isComplexValue stop it, because it is array; when i did debugging : function query in Solr.php $document contain key 'ca' with value ['name1','name2'];

  $entities = array();
            foreach ($response as $document) {
                $entities[] = $this->entityMapper->toEntity($document, $entity);
            }
 if ($this->isComplexValue($property, $value, $metaInformation)) {
                continue;
            }

{"response":{"numFound":918075,"start":0,"docs":[{"id":"0001887-88698229149","ca":["Náplně a tonery - originální"],"cai":[796,758,747,659],"version":1541700906018406400}]}}

I am desperate :)

floriansemm commented 8 years ago

I know the hydration is a bit confusing:

  1. hydrator loads the whole entity from the entity
  2. the mapper replaces the entity-values with the document-values 2.1. if a values is a an set of objects then the document-value will be rejected, we want real objects and the entity still contains objects.

2.1. is the reason why your response values ['name1','name2'] are not mapped. To solve your problem I need your data. But please check in https://github.com/floriansemm/SolrBundle/blob/master/Doctrine/Hydration/DoctrineHydrator.php#L48 if your product-entity ca-property has correct values

hanzx commented 8 years ago

oh, I know what I do wrong. I had different function logic,,,I have empty tables. I need only data from solr, not have to data saved in mysql db. It all works. I need get only multivalued attribute from solr without use mysql, i dont need this values saved in mysql, if you understand me.It is posible ? Sorry my english is bad:) Can I work with facets in this bundle? How ?

floriansemm commented 8 years ago

You can tell the bundle which data it should use: mysql or Solr https://github.com/floriansemm/SolrBundle#configure-hydrationmodes

Solr uses the Solarium-Client which supports Faced Field

hanzx commented 8 years ago

hello :) i understand how ii works, but.... when i use mode HYDRATE_DOCTRINE, everything works, i have data in mysql and my attribute ca return multivalues, nice!!! but when i use mode HYDRATE_INDEX, ca in solr is multivalue, query return result for attribute ca null... this is my problem, i need only solr data, all attriburtes in solr schema with multivalued are returned as null.

floriansemm commented 8 years ago

you should get your ca values in mode HYDRATE_INDEX. sounds like a bug...

hanzx commented 8 years ago

this is my problem from start:)can you check it ? thx

floriansemm commented 8 years ago

I think my last commit 8714d20 solves your problem

hanzx commented 8 years ago

:( return null for multivalue attribute in solr

    public function findById($id)
    {
        $query = $this->solr->createQuery($this->entity);
        $query->setHydrationMode(HydrationModes::HYDRATE_INDEX);
        $query->addSearchTerm('id', '0000284-34');//0000284-34 ; 0002355-107299869
        $result = $query->getResult();

        return $result;
    }
floriansemm commented 8 years ago

try this:

public function findById($id)
    {
        $query = $this->solr->createQuery($this->entity);
        $query->setHydrationMode(HydrationModes::HYDRATE_INDEX);
        $query->addSearchTerm('id', 'category_0000284-34');//0000284-34 ; 0002355-107299869
        $result = $query->getResult();

        return $result;
    }

in https://github.com/floriansemm/SolrBundle/blob/master/Repository/Repository.php#L46 you can see how the base-repository builds a search-query.

hanzx commented 8 years ago
$repo = $this->get('solr.client')->getRepository('AppBundle:Product');
        $prod = $repo->find('0000396-1341');

return null.

dump($query) in Repository->find($id); ??product_0000396-1341, is it okey?

#filterControlCharacters: true
    #fields: array:1 [▼
      "id" => "product_0000396-1341"
    ]
  }

findAll() not work too, only work findBy(['id'=>'0000396-1341']), but not show multivalues