I have some problems with embedding document with Doctrine MongoDB ODM and Symfony 2.
To expose the problem, I have the document product embedOne productInformation, and productInformation embedOne productInformationAddress.
To query, I use something like that :
/**
* #ODM\Document
**/
class product {
/**
* #ODM\EmbedOne(targetDocument="productInformation")
**/
protected $informations;
}
/**
* #ODM\EmbeddedDocument
**/
class productInformations {
/**
* #ODM\EmbedOne(targetDocument="productInformationAddress")
**/
protected $address;
/**
* #ODM\Collection
**/
protected $attr1 = array();
/**
* #ODM\String
**/
protected $attr2
}
/**
* #ODM\EmbeddedDocument
**/
class productInformationAddress {
/** ... suff ... /*
}
When I query :
class productRepository {
public function fetchOne($id) {
return $this->createQueryBuilder()
->field('id')->equals($id)
->getQuery()
->getSingleResult();
}
}
But, I don't understand why I cannot get $product->getInformations()->getAddress(), that always return null...
Any idea?
I don't see a problem with the code you posted, but it would probably be helpful to read through ODM's functional tests for nested, embedded documents. In EmbeddedTest.php, the methods of interest would be anything that uses EmbeddedTestLevel2, which is equivalent to your productInformationAddress class, and testRemoveAddDeepEmbedded().
Related
I am facing an error with symfony and mongoDB odm on one to one relationship
for example i have a user that has Work .
User Class:
/**
* #MongoDB\Document
* #MongoDBUnique(fields="email")
*/
class User implements UserInterface
{
/**
* #MongoDB\Id
*/
private $id;
/**
* #MongoDB\Field(type="string")
*/
private $firstName;
/**
* #MongoDB\Field(type="string")
*/
private $lastName;
/**
* #MongoDB\Field(type="string")
* #Assert\NotBlank()
* #Assert\Email()
*/
private $email;
/**
* #MongoDB\ReferenceOne(targetDocument=Work::class)
*/
private $work;
//getter setter
Work Class:
class Work
{
/**
* #MongoDB\Id()
*/
private $id;
/**
* #MongoDB\ReferenceOne(targetDocument=User::class)
*/
private $user;
//getter setter
}
Controller:
class TestingController extends AbstractController
{
/**
* #Route("/testing", name="testing")
* #param DocumentManager $documentManager
* #return Response
* #throws MongoDBException
*/
public function index(DocumentManager $documentManager)
{
$user = new User();
$user->setFirstName('test1');
$user->setLastName('test2');
$user->setEmail('test123#gmail.com');
$documentManager->persist($user);
$work= new Work();
$work->setUser($user);
$documentManager->persist($work);
$documentManager->flush();
return new Response("test");
}
/**
* #Route("/test", name="test")
* #param DocumentManager $documentManager
* #return Response
*/
public function test(DocumentManager $documentManager){
$user = $documentManager->getRepository(User::class)->findAll();
dump($user);
return new Response("test test");
}
}
So I created 2 classes one as user that has one work, I created the user , then I created a work and i assigned the user from the work class.
in MongoDB compass I got under Work collection a reference for the user.
now in the test method in the controller i try to find the users and dump the data.
The problem is whenever i want to find $user->getWork() i get a null value, while the user exists. but the inverse is working fine . whenever i try $work->getUser() i can find the user.
is there anything wrong in my code ? I want to use both methods : $user->getWork() and $work->getUser(),
I have tried adding to the ReferenceOne mappedBy and inversedBy but its always one of the two methods returns null value.
I think you forgot the mappedBy and inversedBy arguments in the annotation. See the documentation: https://www.doctrine-project.org/projects/doctrine-mongodb-odm/en/2.1/reference/bidirectional-references.html#one-to-one
I want to get a collection of embedded documents. I put data into the database like this:
$dm->getRepository('BundleUserBundle:User')->addRatedPostById($user->getId(), new RatedPost($id, $type));
...which works fine. Now I see new data in mongo console, but when I'm trying to get this data via the getRatedPosts() method, it return null instead of the ArrayCollection. Whats wrong?
Context looks like this:
class User extends BaseUser {
/**
* #MongoDB\EmbedMany(targetDocument="RatedPost")
*/
protected $ratedPosts;
/**
* Add ratedPosts
*
* #param Bundle\UserBundle\Document\RatedPost $ratedPosts
*/
public function addRatedPost(\Bundle\UserBundle\Document\RatedPost $ratedPosts)
{
$this->ratedPosts[] = $ratedPosts;
}
/**
* Remove ratedPosts
*
* #param Bundle\UserBundle\Document\RatedPost $ratedPosts
*/
public function removeRatedPost(\Bundle\UserBundle\Document\RatedPost $ratedPosts)
{
$this->ratedPosts->removeElement($ratedPosts);
}
/**
* Get ratedPosts
*
* #return Doctrine\Common\Collections\Collection $ratedPosts
*/
public function getRatedPosts()
{
return $this->ratedPosts;
}
/**
* #MongoDB\EmbeddedDocument
*/
class RatedPost
{
/**
* #MongoDB\Int
*/
public $post;
/**
* #MongoDB\String
*/
public $rate;
...
}
I had exactly the same problems: saving was no problem but fetching the embedded document was. Turned out it was a "Symfony" caching problem (also on app_dev.php). Have you tried to remove your cache, this worked for me!
I cannot find in doctrine manual how to do a very simple query. I don't know how to manage the equivalent of SQL "JOIN ..." with MongoDb.
abstract class Topic
{
/**
* #MongoDB\Id
*/
protected $id;
}
abstract class Message
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\Date
*/
protected $date;
/**
* #MongoDB\ReferenceOne(targetDocument="Topic")
*/
protected $topic;
}
abstract class User
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\ReferenceMany(targetDocument="Message")
*/
protected $messages;
}
I have a User id and a Topic id.
I want :
1) Find the most recent message from the user
2) Find the most recent message about the topic from the user
$dm->find('User', $id)->getMessages() gives me a "PersistentCollection"
$dm->find('User', $id)->getMessages()->getValues() gives me the array of the messages, but then I have to use PHP loops, i'm sure there is a way to create a query to do that ...
Am I supposed to use map or reduce ?
Can someone help me ? Thanks !
First, you'll have to fix your database schema:
A Message can belong to more than one User?
Usually a Message can have only an author, so I'll change the Message Document to store the author User id:
class Message
{
/**
* #MongoDB\ReferenceOne(targetDocument="User")
*/
protected $author;
//Othe methods...
}
Then to find the most recent Message from user:
class User {
/**
* #ReferenceOne(
* targetDocument="Message",
* mappedBy="author",
* sort={"date"="desc"}
* )
*/
protected $lastMessage;
//Other methods...
}
And to find the most recent message about a topic:
class User {
/**
* #ReferenceOne(
* targetDocument="Message",
* mappedBy="author",
* criteria={"topic" : "sport"}
* sort={"date"="desc"}
* )
*/
protected $lastMessageAboutSport
//Other methods...
}
More info on: Doctrine ODM Complex References Guide
Let me get to the point, I am currently using the Doctrine MongoDB ODM in conjunction with Symfony2 to persist data into MongoDB.
Currently I am grouping my results by type, but I would like to group them by MAX(group_id) as well.
Sure I can just alter the reduce function, but I am trying to steer clear of a large return array and more processing once the query is done, so I was wondering if there is a more elegant solution than that to this particular problem.
The Monitoring document,
/**
* #ODM\Document(collection="monitoring")
*/
class Monitoring
{
/** #ODM\Id */
public $id;
/** #ODM\String */
public $type;
/** #ODM\String */
public $message;
/** #ODM\Int */
public $groupId;
.... getters and setter etc ....
}
MonitoringManager function to fetch all items,
public function getAllMonitoringItems(){
return $this->dm->createQueryBuilder('MonitoringBundle:Monitoring')
->group(array(), array('groups' => array()))
->reduce('function (obj, prev) {
var type = obj.type;
if(!prev.groups.hasOwnProperty(type)){
prev["groups"][type] = [];
prev["groups"][type].push(obj);
} else {
prev["groups"][type].push(obj);
}
}')
->field('type')->notIn(array("graph"))
->getQuery()
->execute()
->toArray();
}
I have to Entities
class Patients
{
/**
* #ORM\OneToOne(targetEntity="ContactAddress", mappedBy="patients")
*/
protected $contactaddress;
}
And another
class ContactAddress
{
/**
* #ORM\OneToOne(targetEntity="Patients", inversedBy="contactaddress")
* #ORM\JoinColumn(name="patient_id", referencedColumnName="id")
*/
protected $patient;
}
When I try execute this code
$em = $this->getDoctrine()->getEntityManager();
$product = $em->getRepository('SurgeryPatientBundle:Patients')->find($id);
I get
No mapping found for field 'patients' on class 'Surgery\PatientBundle\Entity\ContactAddress'.
When i tried get to Contact repository I get result
Please Help ;D
Sorry for my English
You must refer to patient instead of patient*s* in ContactAddress entity.
class Patients
{
/**
* #ORM\OneToOne(targetEntity="ContactAddress", mappedBy="patient")
*/
protected $contactaddress;
}