4

我想将从 Model::find() 返回的 DocumentSet 存储在 memcached 中。但是,当我从缓存中检索结果后尝试处理结果时,我得到了下面的 MongoException。具体来说,使用foreach时,在if ($this->_resource->hasNext())\data\source\mongo_db\Result.php的第63行调用时抛出异常

蒙哥异常

MongoCursor 对象尚未被其构造函数正确初始化

我能理解为什么会这样。

我的问题是,是否有预填充 Model::find() 或创建我自己的 DocumentSet 以便我可以处理数据?通常,我只是将其转换为数组并将其存储在缓存中。但是,我需要访问我编写的一些模型方法(例如:Customer::fullName())

更新:我发现了一些可以但不是很好的解决方法。我将 Model::find() 结果保存为 cache 中的数组$result->to('array')。然后,在检索时,我遍历 $results 并Model::create($result, array("exists" => true)为每个 $result; 填充一个新数组;

4

1 回答 1

4

ADocumentSet返回的Model::find包含一个 Mongo db 游标。在迭代项目之前,它不会从数据库中加载所有数据。在迭代每个项目时,Document会创建 a 并将其缓存在内存中的 DocumentSet 对象中。内置的 php 函数iterator_to_array()可用于将 DocumentSet 转换为可以缓存的文档数组。

正如您在更新中提到的那样,您还可以使用它->to('array')来准备缓存,然后Model::create()将其构建备份。该方法的一个警告:当您使用->to('array')它时,它还会将 MongoId 和 MongoDate 对象分别转换为字符串和整数。如果您$_schema为模型定义了 a 并设置了'id''date'类型,它们将被转换回由Model::create(). 如果您没有所有字段的架构,则可能会出现问题。我最近有一个拉取请求,试图使->to('array')不强制转换本机 mongo 对象成为可能(还解决了在子文档数组中总是强制转换 mongo 对象的问题)。

FWIW,我实际上更喜欢仅将数据保存在缓存中,因为它比序列化整个 php 对象的空间更小,并且避免了从缓存中提取项目时未定义类或未初始化其他项目的潜在问题。

我没有尝试过这个......但我认为你可以制作一个缓存策略类,它会为你透明地处理这个问题。另一个让 Lithium 成为一个非常灵活和强大的框架的非常谨慎的例子。 http://li3.me/docs/lithium/storage/cache/strategy

于 2012-09-09T05:08:09.493 回答