如何通过MongoDB在Doctrine ODM中引用文档进行查找?

cnk*_*nkt 16 doctrine dql mongodb

我的"params"集合中有一个文档,如下所示:

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

引用的文件是这样的:

{
  "_id": ObjectId("4d120a2d2b8d8d3010000000"),
  "code": "car"
}
Run Code Online (Sandbox Code Playgroud)

我正在使用DoctrineODM来获取引用"productType"为"car"的"param"文档.我正在使用此代码:

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

但结果是一个空数组.我怎样才能做到这一点?

And*_*ich 7

如果您使用ReferenceMany或ReferenceOne,则无法通过任何参考文档字段进行查询,除了参考文档ID.

如果您需要code从引用的集合中查询,则应使用EmbedMany而不是ReferenceMany.

在这种情况下,您的文档将是:

{
  "_id": ObjectId("4d124cef3ffcf6f410000037"),
  "code": "color",
  "productTypes": [
     {
       "_id": ObjectId("4d120a2d2b8d8d3010000000"),
       "code": "car"
     }
  ]
}
Run Code Online (Sandbox Code Playgroud)

以下查询将起作用:

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

此外,如果您的ProductType代码是唯一的,您可以使用它代替MongoId,在这种情况下,您可以查询$ id:

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

参考文件:

{
  "_id": 'car'
}
Run Code Online (Sandbox Code Playgroud)

查询:

$query->field('productTypes.$id')->equals('car');
Run Code Online (Sandbox Code Playgroud)

  • 实际上,我接受了 - 部分.在DoctrineODM中的Doctrine\ODM\MongoDB\Persisters中的DocumentPersister-> prepareQueryValue()似乎做了魔术!它在find*查询中转换'referenceVar.idField',这样无论Reference*的底层实现如何,它都可以工作.即似乎findOneBy('referencedDoc.id' - > ... some_id ...)是预期的用法......我不断惊讶于为Mongo构建Doctrine ODM做了多少工作.这是如此巨大,如此深思熟虑! (5认同)
  • 这没有解决这个问题.您不能将Embed*用于所有内容 - 参考*是有原因的.我认为真正的问题是你必须自己查看实际的数据库才能意识到引用被映射为$ varname.id.所以你可以查询:...-> findBy(array('referenceField.id'=> managedDoc-> getId())这绝对不是一个好的解决方案,因为一个人不应该关心甚至不知道内部方式Doctrine做什么参考*协会...... (4认同)

小智 6

您必须使用查询生成器的references()方法来访问@MongoDB\ReferenceOne,例如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();
Run Code Online (Sandbox Code Playgroud)


PS:使用includesReferenceTo()一个@MongoDB\ReferenceMany