MongoDB按引用字段(ORM)过滤


MongoDB filter by reference's field (ORM)

假设我有文档city和文档country

city "引用country: ObjectId("xxxx") country

如何按国家/地区的字段查找城市,例如。 db.Cities.find({"country.code":"US"}

可能吗?我认为不是,但是可以使用MongoDB ORM进行PHP吗?

我试过了

$qb = $this->database->createQueryBuilder(self::NAMESPACE_CITY);
$qb->field('country.code')->equals("US")`

我的City实体包含

/** @ODM'ReferenceOne(targetDocument="'Doctrine'Documents'Country", simple=true) */
protected $country;

文档示例:

<?php
namespace Doctrine'Documents;
use Doctrine'ODM'MongoDB'Mapping'Annotations as ODM;
use Application'Doctrine'Documents'Document;
/** @ODM'Document(collection="Cities") */
class City extends Document {
    /** @ODM'Id */
    protected $_id;
    /** @ODM'ReferenceOne(targetDocument="'Doctrine'Documents'Country", simple=true) */
    protected $country;
}

在单个查询中按国家/地区代码查询城市文档需要联接两个集合,这不受支持。您可以通过首先使用给定代码查找国家/地区(我假设这是一个唯一的字符串)将其分为两个查询。该查询将生成国家/地区的 ObjectId,然后您可以使用该 ObjectId 来查询城市集合:

{ "country": ObjectId(...) }

如果出于某种原因,您想通过国家/地区的一些非唯一值(例如大陆、名称上的子字符串匹配)来查找城市,这仍然可以在两个查询中完成。第一个将再次找到符合标准的任何国家的 ObjectId。然后,第二个查询将使用带有 ObjectId 数组的 $in 运算符:

{ "country": { "$in": [ ObjectId(...), ObjectId(...), ... ]}}

如果您使用的是 Doctrine MongoDB ODM,查询生成器将通过 Expr.php 中的 references()includesReferenceTo() 方法(也通过 Builder.php 公开)支持此功能。 references()includesReferenceTo() 可用于分别匹配 ReferenceOne 或 ReferenceMany 关系中存在的单个文档引用。它们还可以正确处理简单(即只是 ObjectId)和复杂(即 DBRef)引用。

也就是说,ODM 查询生成器没有与多个引用匹配的方法(请注意,上述两种方法都采用单个文档参数)。由于您使用的是简单的引用,因此使用 in() 应该很容易做到这一点,正如我在第二段中提到的;但是,如果我们使用 DBRefs,查询会更复杂(我们需要混合$elemMatch$in,如本答案所述)。我已经在 ODM 项目上打开了问题 #1024 以跟踪此功能请求。

您必须使用 Query Builder 的 references() 方法来实现 @MongoDB''ReferenceOne 像 https://doctrine-mongodb-odm.readthedocs.org/en/latest/reference/query-builder-api.html

$country = $dm->getRepository('Country')->findOneByCode('US');
$queryBuilder = $dm->getRepository('City')->createQueryBuilder()
                   ->field('country')->references($country);
$citiesByCountry = $queryBuilder->getQuery()->execute();


PS: use includeReferenceTo() a @MongoDB''ReferenceMany