我在Symfony环境中使用Doctrine 2 ODM有一个更大的项目。
给定一个简单的ODM实体(XML定义):
<document name="\Document\App" repository-class="\Repository\AppRepository">
<field fieldName="id" type="string" id="true" strategy="UUID"/>
<field fieldName="name" type="string"/>
</document>
我想在App
字段上使用MongoRegex
表达式查询_id
个文档。
现在,我已经意识到&#34; string
与MongoId
&#34;问题 - 我们所有的ID都是正确的字符串。
当我尝试通过MongoDB shell(使用Robomongo作为GUI)时;它很好,因为这个表达式成功地返回了我正在搜索的对象:
App.find({'_id': /^ad.*$/i})
但在PHP环境中,它有所不同。 Doctrine 2 ODM中有一些特殊逻辑,用于处理equals()
搜索与普通equals
不同的标识符字段。
我们的name
实体中有正常的字段App
。如果我们想对其进行类似的搜索,我们会这样做(假设$builder
是instanceof QueryBuilder
)
$builder->field("name")->equals(new \MongoRegex("/^ad.*$/i"));
如果我们检查QueryBuilder
调用$builder->getQueryArray()
的内容,我们会看到:
array (size=1)
'name' =>
object(MongoRegex)[628]
public 'regex' => string '^ad.*$' (length=6)
public 'flags' => string 'i' (length=1)
这很好,而且很有效..我们在那里有MongoRegex
个实例..
标识符字段的所有内容都不同。
让我们这样做:
$builder->field("id")->equals(new \MongoRegex("/^ad.*$/i"));
现在让我们再次检查$builder->getQueryArray()
:
array (size=1)
'_id' => string '/^ad.*$/i' (length=9)
Hm,查询中没有MongoRegex
个实例。事实上,查询不起作用..
这个问题不是这是怎么发生的。我知道怎么做 - 但不是为什么 ..让我们看看Doctrine 2 ODM代码。
此转换发生在Doctrine\ODM\MongoDB\Persisters\DocumentPersister
(see code here)。
摘录:
// Process identifier fields
if (($class->hasField($fieldName) && $class->isIdentifier($fieldName)) || $fieldName === '_id') {
$fieldName = '_id';
if ( ! $prepareValue) {
return array($fieldName, $value);
}
if ( ! is_array($value)) {
return array($fieldName, $class->getDatabaseIdentifierValue($value));
}
如果查询值不是数组(它不是&#39; t,它是MongoRegex
),它将转换为1,并且该值将替换为{{1数据类型getDatabaseIdentifierValue()
(see call here)的数据类型(在本例中为ClassMetaDataInfo
) - 这将是普通字符串而不是string
实例。
所以我们知道 它是如何发生但不是为什么 - 在标识符字段的MongoRegex
操作中进行此转换的原因是什么?有没有必要这样做?
如何使用Doctrine 2 ODM在标识符字段上使用正则表达式进行查询?我们知道它在MongoDB shell中有效,为什么不在这里呢?
我首先将此问题作为SO问题而不是Doctrine 2 ODM问题发布,因为这仍然是一个问题。如果没有人知道为什么要这样做,我会尝试为ODM维护者提出一个Github问题。