16

I have one document in my "params" collection like this:

{
  "_id": ObjectId("4d124cef3ffcf6f410000037"),
  "code": "color",
  "productTypes": [
    {
      "$ref": "productTypes",
      "$id": ObjectId("4d120a2d2b8d8d3010000000"),
      "$db": "test"
    }
  ]
}

the referenced document is this:

{
  "_id": ObjectId("4d120a2d2b8d8d3010000000"),
  "code": "car"
}

I'm using DoctrineODM to fetch the "param" documents which referenced "productType" is "car". I'm using this code:

$query = $dm->createQuery('Cms\Model\Param');
$query->field('productTypes.code')->equals('car');
$result = $query->execute();
var_dump($result);

but the result is an empty array. How can i do this?

cnkt
  • 2,943
  • 5
  • 30
  • 43

3 Answers3

7

You must use the references() method of Query Builder for a @MongoDB\ReferenceOne like https://doctrine-mongodb-odm.readthedocs.org/en/latest/reference/query-builder-api.html

$productType = $dm->getRepository('Cms\Model\ProductTypes')->findOneByCode('car');

$queryBuilder = $dm->getRepository('Cms\Model\Param')->createQueryBuilder()
                   ->field('productTypes')->references($productType);

$results = $queryBuilder->getQuery()->execute();


PS: use includesReferenceTo() a @MongoDB\ReferenceMany

7

If you using ReferenceMany or ReferenceOne you can't query by any reference document field, except reference document id.

If you need query on code from referenced collection you should use EmbedMany instead of ReferenceMany.

In this case your document will be:

{
  "_id": ObjectId("4d124cef3ffcf6f410000037"),
  "code": "color",
  "productTypes": [
     {
       "_id": ObjectId("4d120a2d2b8d8d3010000000"),
       "code": "car"
     }
  ]
}

And following query will work:

$query = $dm->createQuery('Cms\Model\Param');
$query->field('productTypes.code')->equals('car');
$result = $query->execute();
var_dump($result);

Also if your ProductType code is unique you can use it instead of MongoId, in this case you can query on $id:

{
  "_id": ObjectId("4d124cef3ffcf6f410000037"),
  "code": "color",
  "productTypes": [
    {
      "$ref": "productTypes",
      "$id": 'car',
      "$db": "test"
    }
  ]
}

Referenced document:

{
  "_id": 'car'
}

Query:

$query->field('productTypes.$id')->equals('car');
Andrew Orsich
  • 52,935
  • 16
  • 139
  • 134
  • 4
    This doesn't address the question. You can't use Embed* for everything- Reference* is there for a reason. The real problem as I see it is that you have to peek into actual DB on your own to realize that references are mapped as $varname.id. So you can query: ...->findBy(array('referenceField.id' => managedDoc->getId()) Still this is definitely not a good solution because one shouldn't care or even know about internal way Doctrine does Reference* associations... – Jakub P. Oct 14 '11 at 15:12
  • 5
    Actually, I take that back - partially. DocumentPersister->prepareQueryValue() in Doctrine\ODM\MongoDB\Persisters in DoctrineODM seems to do the magic! It converts 'referenceVar.idField' in the find* queries so that regardless of the underlying implementation of Reference* it will work. I.e. it seems that findOneBy('referencedDoc.id' -> ...some_id...) is the intended usage... I am continually amazed at how much work has gone into building Doctrine ODM for Mongo. It's so huge and so well thought out! – Jakub P. Oct 14 '11 at 15:24
  • 1
    @JakubP. How about adding these comments as an answer. – Tim Lytle Jan 12 '12 at 14:56
  • Just a heads up to anyone wondering in the future... you have to create the index for productTypes.$id within Mongo or else DoctrineODM throws an exception saying there is no index (despite this working in Mongo CLI) – creamcheese Jun 26 '13 at 16:25
0
->field('productTypes.code')->equals(new \MongoRegex('/.*car.*/i'))
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339