使用一个status_history
表,它将保存entries
中特定记录的状态修改日期和时间,我试图找到最简单的方法来获取当前状态,也就是最近日期的状态。
例如,考虑以下内容:status_history
+----+----------+------------+-----------+
| id | entry_id | status | timestamp |
+----+----------+------------+-----------+
| 1 | 1 | Processing | 15:05:09 |
| 2 | 1 | In Review | 15:05:18 |
| 3 | 1 | Complete | 15:05:26 |
+----+----------+------------+-----------+
当然,我们的条目:entries
+----+--------+
| id | title |
+----+--------+
| 1 | Foobar |
+----+--------+
如何使用DQL检索特定条目的最新状态(技术上为当前状态),而不必在Entry
实体中维护latest_status_id
列?
考虑调用$entry->getCurrentStatus()
将返回"Complete"
。然而,如果该条目有大量的状态记录,那么第二个加载所有状态的查询可能会导致性能下降。
注意:在本文中,他们用额外的列方法描述了它,使用了用于并发的锁定机制。我希望避免这种方法,除非这是正确的方法,因为我们试图不对每个表(status_history.entry_id
和entry.latest_history_id
)都有双重关系。
对于单个条目,查询可能如下所示:
$query = $em->createQuery('SELECT e, s
FROM entries e
JOIN e.status_history s
WHERE e.entry_id = :entry_id
ORDER BY s.timestamp DESC');
$query->setParameter('entry_id', $entry_id);
$entries = $query->getSingleResult();
在getCurrentStatus()
方法中,您可以返回指定的唯一status_history对象。
对于所有条目,它都比较复杂,并且必须使用具有GROUP BY
和MAX()
的子查询。它在本机SQL中是可行的,但我还没有弄清楚如何使用DQL。一旦我有了解决方案,我就会更新我的答案。
我认为在状态历史存储库中使用QueryBuilder
就足够了:
$entry_id = 1;
$queryBuilder = $this->createQueryBuilder()
->select('s')
->where('s.entry = :entry_id')
->orderBy('o.id', 'DESC')
->setParameter('entry_id', $entry_id)
$query = $queryBuilder->getQuery();
return $query->getSingleResult();
您可以使用id,假设id是"自动递增",并且timestamp
是创建记录的自动时间戳。在这种情况下,最高id总是最新的插入,所以您甚至不需要使用timestamp
列来查找该记录。
否则,您必须在timestamp
列中添加一个索引,然后按该列排序:
$entry_id = 1;
$queryBuilder = $this->createQueryBuilder()
->select('s')
->where('s.entry = :entry_id')
->orderBy('o.timestamp', 'DESC')
->setParameter('entry_id', $entry_id)
$query = $queryBuilder->getQuery();
return $query->getSingleResult();
您需要在timestamp
列中添加一个索引以提高的性能