I have a document with an index defined.
/** #ODM\Document */
class Stat
{
/** #ODM\Id(strategy="NONE", type="int") */
private $id;
/** #ODM\Field(type="string") */
private $period;
/** #ODM\ReferenceOne(targetDocument="Player") */
private $player;
/** #ODM\Field(type="string") #ODM\Index */
private $statType;
However, when I look at the indexes created in the collection, the only index is the _id.
To save the document I'm doing:
$stat = new Documents\Stat();
$stat->setId(1);
$stat->setPlayer($player);
$stat->setPeriod(1);
$stat->setStatType('goal');
$dm->persist($stat);
$dm->flush();
Is there something else I'm not doing?
Indexes are not created (nor ensured if they're in sync with mapping) during normal ODM usage.
If you're using Symfony then solving problem is easy, just run doctrine:mongodb:schema:create command from Symfony's console (and if you're using other framework, look for equivalent as command itself is provided by ODM).
If you want to control indexes from your code you can use SchemaManager which provides an API to control "schema" directly (you can also control indexes on per-document basis). Obtaining it is easy: $sm = $dm->getSchemaManager();.
// AppBundle/Document
namespace AppBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique as MongoDBUnique;
/**
* #MongoDB\Document(repositoryClass="AppBundle\Repository\ProduitRepository")
* #MongoDBUnique(fields="$noProduit")
*/
class Produit
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\String
* #MongoDB\UniqueIndex(order="asc")
*/
protected $noProduit;
/**
* #MongoDB\Field(type="string")
*/
protected $libelle;
// getter and setter
}
// AppBundle/Controller
$dm = $this->get('doctrine_mongodb')->getManager();
$dm->getSchemaManager()->ensureIndexes();
schema and database will be created automatically when you run your app.
For more info
visit this link
/**
* #ODM\Document
* #ODM\Indexes({
* #ODM\Index(keys={"statType"="asc"}),
* #ODM\UniqueIndex(keys={"period"="asc"})//For example unique index
* })
*/
class Stat
{
}
Then if you use symfony run php bin/console doctrine:mongodb:schema:create
Related
I'm using API-Platform and faced an issue with updating many-to-many with an empty value.
Here is the small example:
/**
* Many Organizations have Many Followers.
* #ORM\ManyToMany(targetEntity="App\Entity\User\User", inversedBy="organizations")
* #ORM\JoinTable(name="organizations_followers",
* joinColumns={#ORM\JoinColumn(name="organization_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id", unique=true)}
* )
*/
protected $followers;
/**
* #return Collection
*/
public function getFollowers(): Collection
{
return $this->followers;
}
/**
* #param array $followers
*/
public function setFollowers(array $followers): void
{
$this->followers = $followers;
}
/**
* Organization constructor.
*/
public function __construct()
{
$this->id = Uuid::uuid4();
$this->followers = new ArrayCollection();
}
So, when I'm trying to delete all followers (PATCH request with empty followers in the relationships field) I always get one undeleted record. What am I doing wrong? Any Ideas?
Just example:
/**
* #ORM\Entity
*/
class Menu
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="MenuDish", mappedBy="menu", fetch="EAGER")
*/
private $menu_dishes;
public function __construct()
{
$this->menu_dishes = new ArrayCollection();
}
}
/**
* #ORM\Entity
*/
class MenuDish
{
/**
* #ORM\ManyToOne(targetEntity="Dish", inversedBy="menu_dishes", fetch="EAGER")
*/
private $dish;
}
Then i trying to get menu:
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository(Menu::class);
$menu = $repo->find(1);
Then I look into XDebug and see that Menu::$menu_dishes is Collection of Entities (not proxies) all is OK, EAGER working.
BUT Menu::$menu_dishes::$dish contains Proxy ! There is a bug? $dish marked with fetch=EAGER.
When I mark some property as FETCH=EAGER I expect that this property will not contain Proxy class.
I need it for fighting with SoftDelete, the real issue is that $dish is actually soft deleted, and fetch eager may fix it by setting $dish as null, but it is not working.
Ho to make EAGER working on dish property?
I wonder if there is any way to find out if a record has references.
I have the following entity:
class Item extends Entity
{
/**
* #Id #GeneratedValue
* #Column(name="id")
*/
protected $id;
/**
* #OneToMany(targetEntity="Citation", mappedBy="citation")
*/
protected $citedIn;
/**
* #Column(name="stamped", type="boolean")
*/
protected $stamped;
/** ... rest of the code ... */
}
And I want to perform the following check:
$qb
->select("
COUNT(i.id),
WHEN (i.stamped = true) THEN 'stamped'
WHEN (i.citedIn IS NOT NULL) THEN 'cited'
ELSE 'just started'
END current_status
")
->from(Entity\Item::class, 'i')
->groupBy('current_status');
Note that I tried to use i.citedIn IS NOT NULL, but it didn't work. What could I use instead?
Since it is a OneToMany relationship I think you need to use IS NOT EMPTY instead of IS NOT NULL. Doctrine will create an empty ArrayCollection for each entity, so technically it's not null, because it's an empty array.
Update
If that doesn't work, try NOT INSTANCE OF YourApp\Model\Citation.
I'm searching why I get an error with my mapping but, I really don't see. I red some issues in stack but it doesn't work for me.
The error :
The association CTC\Bundle\UserBundle\Entity\Address#addressType refers to the inverse side field CTC\Bundle\AdminBundle\Entity\AddressType#addresses which does not exist.
Secondly, I also wonder me why when I use my "doctrine:generate:entities ...", that doesn't give me the getter and setter for addresses but well for addressType.
Here is my mapping code :
class AddressType
...
/*
* #var array
*
* #ORM\OneToMany(targetEntity="CTC\Bundle\UserBundle\Entity\Address", mappedBy="addressType")
*
*/
private $addresses;
public function __construct()
{
$this->addresses = new ArrayCollection();
}
...
Class Address
/**
* #ORM\ManyToOne(targetEntity="CTC\Bundle\AdminBundle\Entity\AddressType", inversedBy="addresses")
* #ORM\JoinColumn(name="addressTypeID", referencedColumnName="AddressTypeID")
*/
private $addressType;
Any help would be very appreciate.
Ok, It was just a problem of * !
In the AddressType class, I change this
/*
* #var array
*
* #ORM\OneToMany(targetEntity="CTC\Bundle\UserBundle\Entity\Address", mappedBy="addressType")
*
*/
private $addresses;
by this
I just add ONE "" after "/" and everything works !
/**
* #var array
*
* #ORM\OneToMany(targetEntity="CTC\Bundle\UserBundle\Entity\Address", mappedBy="addressType")
*
*/
private $addresses;
/*
* #var array
*
* #ORM\OneToMany(targetEntity="CTC\Bundle\UserBundle\Entity\Address", mappedBy="addressType", cascade={"persist","remove"})
*
*/
private $addresses;
public function __construct()
{
$this->addresses = new ArrayCollection();
}
/**
* #ORM\ManyToOne(targetEntity="CTC\Bundle\AdminBundle\Entity\AddressType", inversedBy="addresses")
* #ORM\JoinColumn(name="addressTypeID", referencedColumnName="id")
*/
private $addressType;
I think your property name for Id inside addressType entity is not AddressTypeID , I cann't write commit to ask this :( I hope this work phone you
I have two tables/entities client and site that have a many to many relationship combined by a join table client_site. Here are how my entities are setup.
Here is the client table entity
/**
* #Entity
* #Table(name="client")
*/
class Client
{
/**
* #Id #Column(type="bigint")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ManyToMany(targetEntity="Site", inversedBy="clients")
* #JoinTable(name="client_site",
* joinColumns={#JoinColumn(name="c_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="s_id", referencedColumnName="id")}
* )
*/
private $sites;
And the site table entity
/**
* #Entity
* #Table(name="site")
*/
class Site
{
/**
* #Id #Column(type="bigint")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ManyToMany(targetEntity="Client", mappedBy="sites")
*/
private $clients;
This is the client_site table entity
/**
* #Entity
* #Table(name="client_site",indexes={#index(name="FK_client_site",columns={"c_id"}),#index(name="FK_client_site_2",columns={"s_id"})})
*/
class ClientSite
{
/**
* #Id
* #ManyToOne(targetEntity="Client", inversedBy="ClientSite")
*/
private $client;
/**
* #Id
* #ManyToOne(targetEntity="Site", inversedBy="ClientSite")
*/
private $site;
This is the query I am trying to run
$query = Zend_Registry::get('em')
->createQuery('SELECT c, s
FROM Application\Models\Client c
JOIN c.sites s
WHERE c.is_active = 1');
$clients = $query->getResult();
And this is my error
No identifier/primary key specified for Entity 'Application\Models\ClientSite'. Every Entity must have an identifier/primary key.
I put the #Id on both fields in the ClientSite entity, as they are the composite primary keys for my joiner table. Can this not be done in Doctrine2? If it can't, what are my alternative options.
If you CAN do this, what have I done incorrectly?
This isn't currently supported by Doctrine 2.
However, they are working on adding support for this in an experimental branch. Apparently this might be included in the 2.1 release if it works without issues.