基于实体属性值查询所有对象


Query all objects based on entity property value?

我的实体中有一个自定义属性:

public function getStockSoldPercentage()
{
    return ($this->getStockSold() / $this->getFullStock()) * 100;
}

通过使用此属性,我可以访问库存售罄的百分比。目前我使用的是类似的查询

$bestellers = $this->getDoctrine()->getRepository('CoreBundle:Products')->findAll();

并直接在我的小树枝模板中处理对象(百分比高于例如75%的所有产品)的过滤。所以你看,这在缩放方面不是很好。当我每次用户访问网站时都要查询1000个产品时,这太过分了…

我想构建一个自定义实体存储库,类似于findAllBestSellers(),只查询getStockSoldPercentage()属性高于75的所有对象。

我该怎么做?

编辑:

getStockSold()getFullStock()不是字段,而是函数。它们看起来像这样:

public function getFullStock()
{
    $stock = 0;
    foreach ($this->variants as $variant) {
        $stock += $variant->getStock();
    }
    return $stock;
}
public function getStockSold()
{
    return $this->getFullStock() - $this->getCurrentStock();
}

事实上,应用程序逻辑需要太复杂,无法在应用程序中以另一种方式实现。您不能简单地请求SQL中的数据库来获得您想要的内容。

但是,我建议你创建一个sql函数,它会返回你的产品,并在其中记录你的所有逻辑。这将在你的应用服务器上实现负载平衡,mysql的效率要高得多。

之后,您可以通过以下操作调用您的函数:

public function findAllBestSellers() {
    $sql = "SELECT PRODUCTS_WITH_STOCK_SOLD_PERCENTAGE() AS products";
    $stmt = $this->dbal->executeQuery($sql);
    $stmt->execute();
    return current($stmt->fetch());
}

解决问题的另一种方法:

//In your controller
$bestsellers = $this->getDoctrine()->getRepository('CoreBundle:Products')->findAll();
$results = [];
foreach ($bestsellers as $bestseller) {
    if ($bestseller->getStockSoldPercentage() >= '75') {
        $results[] = $bestseller;
    }
} 
return $this->render('YourTemplate.html.twig', ["results" = > $results]);

这实际上是许多应用程序将具有两个数据库的经典示例。一个用于实时更新,另一个用于报告。

考虑每次出售股票时计算新股票的出售百分比,然后将价值存储在某个地方。这显然会减慢你的个人股票交易速度,但会大大加快你的报告查询速度。这是否是一个可以接受的交易取决于你。

最终,你可以转向一个更基于事件的系统,在这个系统中,出售股票会触发一条消息。一个完全独立的过程会监听这些消息,并相应地更新您的报告表。这将两全其美。