How to make the index on Table for speeding up searching.
I have two tables like these
(I created tables with doctorine from symfony2, but in fetching use plain mysql from python script.)
Now I want to exec this sql many times(changing x value)
select recordDate,closePrice from PriceDay where company_price=x ORDER BY recordDate DESC
So I wan to set the index like indexes={#ORM\Index(name="code_index",columns={"company_price","recordDate"})}) , but I am not sure it is the best solution or not. Pairs of company_price and recordDate are unique. Could you help some ideas??
* #ORM\Table(indexes={#ORM\Index(name="code_index",columns={"company_price","recordDate"})})
PriceDay table
class PriceDay
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Acme\UserBundle\Entity\Company")
* #ORM\JoinColumn(name="company_price", referencedColumnName="id")
*/
private $company;
/**
* #ORM\Column(type="float")
*/
private $closePrice = 0;
/**
*
* #ORM\Column(type="date")
*/
private $recordDate;
Company Table
class Company
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string",nullable=false)
*/
private $name;
/**
* #var boolean
* #ORM\Column(name="enabled",type="boolean")
*/
private $enabled = true;
Related
sorry for my poor english btw , it's not my mother's tongue .
So i created an API using FOSRestBundle on syfmony 3 :
This one :
public function getHoraireAction(){
$Horaire = $this->getDoctrine()->getRepository('CBMedBundle:Horaire')- >findAll();
if(!$Horaire){
throw $this->createNotFoundException();
}
return $Horaire;
}
Entity Horaire.php with JMSSerializer
<?php
namespace CBMedBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\VirtualProperty;
/**
* Horaire
*
* #ORM\Table(name="horaire")
* #ORM\Entity(repositoryClass="CBMedBundle\Repository\HoraireRepository")
*
* #ExclusionPolicy("all")
*/
class Horaire
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var time
*
* #ORM\Column(name="Debut", type="time", length=10)
* #Expose
*/
private $debut;
/**
* #var time
*
* #ORM\Column(name="EntreeSalle", type="time", length=10)
* #Expose
*/
private $entreeSalle;
/**
* #var time
*
* #ORM\Column(name="HeureAnesthesie", type="time", length=10)
* #Expose
*/
private $heureAnesthesie;
/**
* #var time
*
* #ORM\Column(name="Operation", type="time", length=10)
* #Expose
*/
private $operation;
/**
* #var time
*
* #ORM\Column(name="incision", type="time", length=10)
* #Expose
*/
private $incision;
/**
* #var time
*
* #ORM\Column(name="finOpe", type="time", length=10)
* #Expose
*/
private $finOpe;
/**
* #var time
*
* #ORM\Column(name="Reveil", type="time", length=10)
* #Expose
*/
private $reveil;
/**
* #var time
*
* #ORM\Column(name="Sortie", type="time", length=10)
* #Expose
*/
private $sortie;
/**
* #ORM\OneToOne(targetEntity="CBMedBundle\Entity\Interventions", cascade= {"persist"})
* #Expose
*/
private $Interventions;
etc..
Everything is working , but it seems that the API do not return the true value of fields who have "time" type .
Horaire.php date time datas on mysql
And this is what i get when i test the API (using post man)
Error with Date time
How to fix that please .
Thanks
Ok i have found the solution .
i had to add these lines :
use JMS\Serializer\Annotation\Type;
//.....
/**
* #var time
*
* #ORM\Column(name="Debut", type="time", length=10)
* #Type("DateTime<'h-m-s'>")
* #Expose
*/
private $debut;
etc..
Basically, I have two entities, Place and Event:
/**
* Place
*
* #ORM\Table(name="place")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PlaceRepository")
*/
class Place
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Event", mappedBy="place")
*/
private $events;
}
and
class Event
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
* #JMS\Type("DateTime<'H:i'>")
* #ORM\Column(name="event_starts", type="datetime")
*/
private $eventStarts;
/**
* #var \DateTime
* #JMS\Type("DateTime<'Y/m/d H:i'>")
* #ORM\Column(name="event_ends", type="datetime", nullable=true)
*/
private $eventEnds;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="event_id", type="string", length=70)
*/
private $event_id;
/**
* #JMS\Exclude()
* #ORM\ManyToOne(targetEntity="Place")
* #ORM\JoinColumn(name="place_id", referencedColumnName="id")
*/
private $place;
When I'm querying Places, I would like that not all Events would be joined, but only those which are taking place today (eventStarts = today). Is there a way to do it only with Doctrine or MySQL?
Pretty straightforward.
$qb = $this->getEntityManager()->createQueryBuilder();
If you want to only get places which have an event in a specific date range:
$data = $qb->select('p, e')
->from('YourBundle:Place', 'p')
->join('p.events', 'e')
->where($qb->expr()->between('e.eventStarts', ':start', ':end'))
->setParameter('start', $someStartDateTimeObject)
->setParameter('end', $someEndDateTimeObject)
->getQuery()
->getResult();
If you would like to get all places, even if they don't have an event, but join an event if there is one in the specified range:
$data = $qb->select('p, e')
->from('YourBundle:Place', 'p')
->leftJoin('p.events', 'e', 'WITH', $qb->expr()->between('e.eventStarts', ':start', ':end'))
->setParameter('start', $someStartDateTimeObject)
->setParameter('end', $someEndDateTimeObject)
->getQuery()
->getResult();
I have the following entities (simplified):
a work is composed of multiple tasks. Each task has a field storing the time it should be due and a field storing the time it has been completed.
/**
* Work
*
* #ORM\Entity
*/
class Work
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Task", mappedBy="work", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="task_work_id", referencedColumnName="id")
*/
protected $task;
/**
* Constructor
*/
public function __construct()
{
$this->task = new ArrayCollection();
}
}
/**
* Task
*
* #ORM\Entity
*/
class Task
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Work", inversedBy="task")
* #ORM\JoinColumn(name="work_id", referencedColumnName="id")
*/
private $work;
/**
* #var \DateTime
*
* #ORM\Column(name="completed", type="datetime", nullable=true)
*/
private $completed;
/**
* #var \DateTime
*
* #ORM\Column(name="duedate", type="datetime", nullable=true)
*/
private $duedate;
}
I am trying to build a query to retrieve all works that have uncompleted overdue tasks.
I initially thought something like this:
$repository = $this->getEntityManager()
->getRepository('MyBundle:Work');
$query = $repository->createQueryBuilder('v');
$query->leftJoin('v.task', 't');
$query->andWhere(
$query->expr()->isNull('t.completed')
)
->andWhere(
$query->expr()->gte('t.duedate', ':now')
)
;
$query->setParameter('now', new \DateTime(), \Doctrine\DBAL\Types\Type::DATETIME);
However, this retrieves works whose all tasks are overdue (I think).
So I tried with a sub-query:
$repository = $this->getEntityManager()
->getRepository('MyBundle:Work');
$query = $repository->createQueryBuilder('v');
$query2 = $this->getEntityManager()
->createQueryBuilder();
$query2->select('t')
->from('v.task', 't');
$query2->andWhere(
$query->expr()->isNull('t.completed')
)
->andWhere(
$query->expr()->gte('t.duedate', ':now')
)
;
$query2->setParameter('now', new \DateTime(), \Doctrine\DBAL\Types\Type::DATETIME);
$query->andWhere(
$query->expr()->any(
$query2->getDql()
)
);
But I get the following error:
QueryException: [Syntax Error] line 0, col 104: Error: Expected known function, got 'ANY'
Any idea on how I could write the query?
Thank you in advance!
You have not defined a repository for $query2
I have one table tech_note and I would like to have 3 tables more tech_note_es, tech_note_en and tech_note_fr (in a future many more tables). And the tech_note can be in the 3 tables at same time.
My idea is attach to tech_note_en and automatically receive attributes from tech_note.
SECOND EDIT:
I would like somthing like that: I search in Tech_note_EN by ID=3 (I recive fields from tech_note_EN with ID=3 and fields tech_note with ID=3.
But if I search in Tech_note_ES BY ID=3 (I recive fields from tech_note_ES with ID=3 and tech_note fields from tech_note with ID=3 (the same fields from above)
The tech_note have a ID=3. Tech_note_EN have ID=3, and Tech_note_ES have ID=3
EDIT WITH NEW CLASSES:
Now I have this error:
Entity 'EVTS\FrontendBundle\Entity\Tech_note_en' has a composite identifier but uses an ID generator other than manually assigning (Identity, Sequence). This is not supported.
TECH_NOTE
abstract class Tech_note {
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var datetime $control_date
*
* #ORM\Column(name="control_date", type="datetime")
*/
private $control_date;
/**
* #var string $comment
*
* #ORM\Column(name="comment", type="string")
*/
private $comment;
TECH_NOTE_EN
class Tech_note_en extends Tech_note {
/**
* #var integer $tech_note_id
*
* #ORM\Id
* #ORM\Column(name="tech_note_id", type="integer")
* #ORM\OneToOne(targetEntity="tech_note")
* #ORM\JoinColumn(name="tech_note_id",referencedColumnName="id")
*/
private $tech_note_id;
/**
* #var text $symptom
*
* #ORM\Column(name="symptom", type="text")
*/
private $symptom;
/**
* #var text $cause
*
* #ORM\Column(name="cause", type="text")
*/
private $cause;
/**
* #var string $solution
*
* #ORM\Column(name="solution", type="string")
*/
private $solution;
OLD CLASSES
TECH_NOTE
class Tech_note {
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var datetime $control_date
*
* #ORM\Column(name="control_date", type="datetime")
*/
private $control_date;
/**
* #var string $comment
*
* #ORM\Column(name="comment", type="string")
*/
private $comment;
TECH_NOTE_EN
class Tech_note_en
{
/**
* #var integer $tech_note_id
*
* #ORM\Id
* #ORM\Column(name="tech_note_id", type="integer")
* #ORM\OneToOne(targetEntity="tech_note")
* #ORM\JoinColumn(name="tech_note_id",referencedColumnName="id")
*/
private $tech_note_id;
/**
* #var text $symptom
*
* #ORM\Column(name="symptom", type="text")
*/
private $symptom;
/**
* #var text $cause
*
* #ORM\Column(name="cause", type="text")
*/
private $cause;
/**
* #var string $solution
*
* #ORM\Column(name="solution", type="string")
*/
private $solution;
There is an awesome solution to your problem, which is single table inheritance
What this does is basically Have one central table with general fields, and links to other table with specific fields.
In your case I would use this architectural model:
abstract class TechNote (abstract common entity, which contains common fields)
class TechNoteEn extends TechNote (specific entity which inherits common fields and adds specific EN fields)
and so on.
I find this as the best architectural solution for your problem.
That's your ORM's job.
// Assuming $tech_note_en is a Tech_note_en instance
$tech_note_en->getTechNote();
(something like this ^^)
I have problem with doctrine 2.
I have following db tables :
So, Doctrine generate entities which retrive data from desk settings for site, but I need, to retrieve all settings from desk_settings table and overwrite its values from desk_settings_values table using desk_id
DB image -> https://docs.google.com/file/d/0B7rOFTJGfJwTWEQ3bXZFU1hXZlU/edit?usp=sharing
Doctrine entities which was generate with script:
/**
* Desk
*
* #ORM\Table(name="desk")
* #ORM\Entity
*/
class Desk
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="code", type="string", length=100, nullable=false)
*/
private $code;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255, nullable=false)
*/
private $description;
/**
* #var \DateTime
*
* #ORM\Column(name="created", type="datetime", nullable=false)
*/
private $created;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="PayBox\Entity\DeskSettings", mappedBy="desk")
*/
private $deskSettings;
}
use Doctrine\ORM\Mapping as ORM;
/**
* DeskSettings
*
* #ORM\Table(name="desk_settings")
* #ORM\Entity
*/
class DeskSettings
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="setting_key", type="string", length=100, nullable=false)
*/
private $settingKey;
/**
* #var string
*
* #ORM\Column(name="setting_value", type="string", length=255, nullable=false)
*/
private $settingValue;
/**
* #var \DateTime
*
* #ORM\Column(name="created", type="datetime", nullable=false)
*/
private $created;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="PayBox\Entity\Desk", inversedBy="deskSettings")
* #ORM\JoinTable(name="desk_settings_values",
* joinColumns={
* #ORM\JoinColumn(name="desk_settings_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="desk_id", referencedColumnName="id")
* }
* )
*/
private $desk;
}
From Doctrine documentation:
Why are many-to-many associations less common? Because frequently you
want to associate additional attributes with an association, in which
case you introduce an association class. Consequently, the direct
many-to-many association disappears and is replaced by
one-to-many/many-to-one associations between the 3 participating
classes.
You need to change your class structure to one-to-many/many-to-one. See this blog.