CollectionsCriteria::expr(), isNotNull and notLike


CollectionsCriteria::expr(), isNotNull and notLike

我正在使用Doctrine'Common'Collections'Criteria::expr()NOT查询生成器表达式)。

isNotNull()notLike()运算符似乎没有在这个类中实现。

在这种情况下,执行isNotNull()notLike()的最佳方法是什么?

条件不为空

doctrine/orm ^2.4doctrine/collections ^1.2中,要具有与Criteria::expr()->isNotNull('field')类似的is not null,可以使用

$criteria = Criteria::create();
$expr = $criteria::expr();
$collection->matching($criteria->where($expr->neq('field', null)));

这与表达式生成器创建Expr::isNull的方式相同,但通过:将比较运算符更改为Comparison::NEQ

return new Comparison($field, Comparison::EQ, new Value(null));

然后由QueryExpressionVisitorBasicEntityPersister进行检查,用于将查询构建为Expr:isNotNull

case Comparison::NEQ:
    if ($this->walkValue($comparison->getValue()) === null) {
        return $this->expr->isNotNull($this->rootAlias . '.' . $comparison->getField());
    }

标准LIKE和NOT LIKE

对于Criteria::expr()->like()功能,Criteria::expr()->contains('property', 'value')等效于SQL property LIKE %value%。但是,它不允许更改为value%%value,而是使用已与master合并的建议的startsWithendsWith方法的拉取请求(自2.5.4起),因此可以与2.5.5一起发布。

不幸的是,对于Criteria::expr()->notLike()和其他LIKE变体,Criteria使用的'Doctrine'Common'Collections'ExpressionBuilder不支持它们。

此外,如果未定义比较运算符(如Comparison::CONTAINS,则QueryExpressionVisitorBasicEntityPersister会引发错误,从而阻止手动定义自己的Comparison功能。

https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#filtering-集合


自定义存储库备选方案

最好的替代方案是使用自定义存储库和DBAL查询生成器表达式来替换所需的功能。

使用自定义实体存储库来过滤结果集将防止对集合进行完整的表读取,并提高使用缓存时的速度。

https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#custom-存储库


集合筛选器备选方案

另一种选择是使用filter来检索集合中的特定对象子集。

https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/query-builder.html#the-expr级

class MyEntity
{
    public function getCollectionFieldNotLike($value)
    {
        return $this->getCollection()->filter(function($a) use ($value) {
            return (false === stripos($a->getField(), $value));
        });
    }
    public function getCollectionFieldLike($value)
    {
        return $this->getCollection()->filter(function($a) use ($value) {
            return (false !== stripos($a->getField(), $value));
        });
    }
}
$entity->getCollectionFieldNotLike('value');
$entity->getCollectionFieldLike('value');

用于存储库中两者的过程语法组合。

$criteria = Criteria::create();
$expr = $criteria::expr();
$criteria->where($expr->neq('field', null));
$collection = $entityManager->getRepository('app:MyEntity')->matching($criteria);
$collectionNotLike =  $collection->filter(function($a) {
    return (false === strpos($a->getField(), 'value'));
});

请记住,如上所述,这将强制对集合读取完整的表,因为它需要检索记录才能过滤结果。