mongodb-odm: Wrong mapping of $id field.
I think this is a wrong behaviour about mapping field in an embedded document. I’m using version: 3.1.0
This is my example:
Main document
/**
* @ODM\Document
*/
class Main
{
/**
* @ODM\Id
*/
private $id;
/**
* @ODM\EmbedMany(targetDocument="Embedded")
*/
protected $embedded;
}
Embedded document
/**
* @ODM\EmbeddedDocument
*/
class Embedded
{
/**
* @ODM\Field(type="string")
*/
protected $id;
/**
* @ODM\Field(type="boolean")
*/
protected $active;
}
In the embedded document there is a field called $id that is a string type, not @ODM\Id.
The problem comes when i try to query that field.
$qb
->field('embedded')->elemMatch($qb->expr()
->field('id')->equals(1)
)
;
$qb->getQuery()->execute();
This will result in this query:
"embedded":{"$elemMatch":{"_id":{"$id":"5a0d7aee26567e3c36166391"}}}
But i suppose to have:
"embedded":{"$elemMatch":{"id":1}}
So I investigate in the mapField function and i noticed that:
Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo line 1063: public function mapField(array $mapping)
if (isset($mapping['id']) && $mapping['id'] === true) {
$mapping['name'] = '_id';
$this->identifier = $mapping['fieldName'];
...
}
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 16 (8 by maintainers)
@iskyd @webdevilopers #2299 fixes the original issue where the wrong
ClassMetadata
instance was used. I’ll revisit the problem of conflicting field names separately, but the PR should fix most issues when using anExpr
on an association with its own metadata.I will have to correct myself on the last comment. Indeed our solution on order to keep the domain model clean and stay with our internal “$id” property we can do this:
@KarunaGovind, @webdevilopers
In ODM, both field name and name (aka database name) are immediately reserved and required to be unique. There may not be a field with a name equal to another fields
fieldName
attribute. The reason for this is because it’s possible for you to create a query like this:In this case, we wouldn’t want you to have to know how exactly
someReference
is mapped (as ID, DBRef or ref). Also, you shouldn’t have to know what identifier$someObject
uses. So, we use mapping information as well as thesomeReference
fieldName to get to this query object:This replicates behaviour from ORM, which is why it was built this way. Unfortunately, in your case this means that you’ll have to find a different
fieldName
for your id field unless you can change the schema (which isn’t always possible).In the original example, this is a bit different: the query expression contains metadata for the original it was built for, which is why the
id
field is changed to_id
. That’s why changing the classMetadata instance in the expression object yields the correct result. One possible fix here is adding an optional$field
argument toexpr()
which would allow you to get an expression based on the metadata of a nested field. I’ll see if we can fix this in 1.2 or 1.3.