2012-02-29 60 views
6

我需要存储一些基本上只是日期/整数键值对的数据,其中日期将始终是唯一的。MongoDB - 有可能通过关联数组键来查询吗?

我希望能够将它存储就像一个关联数组:

array(
    "2012-02-26" => 5, 
    "2012-02-27" => 2, 
    "2012-02-28" => 17, 
    "2012-02-29" => 4 
) 

,但我也需要能够查询的日期(即把一切在那里日期> 2012-02-27 ),所以怀疑我需要使用模式更像是:

array(
    array("date"=>"2012-02-26", "value"=>5), 
    array("date"=>"2012-02-27", "value"=>2), 
    array("date"=>"2012-02-28", "value"=>17), 
    array("date"=>"2012-02-29", "value"=>4), 
) 

显然,前者是更清洁和更简洁,但我可以查询它,我想要的方式,如果没有其他可能更合适的模式?

+0

http://www.php.net/manual/en/mongo.queries.php – 2012-02-29 20:56:55

+0

我不会以这种格式存储日期。使用时间();功能。这将使排序日期等更容易。 http://php.net/manual/en/function.time。php – 2012-02-29 20:59:24

回答

10

你已经描述了两种方法,让我分解它们。

方法#1 - 关联数组

用于通过 “关联数组” 查询的关键工具是$exists运算符。 Here是运营商的详细信息。

所以你绝对可以运行类似下面的查询:

db.coll.find({ $exists: { 'field.2012-02-27' } }); 

根据您的描述您正在寻找不与$exists运营商配合地很好范围查询。 “关联数组”版本也很难索引。

方法#2 - 对象的数组

这无疑具有更好的查询功能:

db.coll.find({ 'field.date': { $gt: '2012-02-27' } }); 

它也可以被索引

db.coll.ensureIndex({ 'field.date': 1 }); 

然而,有一个与贸易关闭更新。如果你想增加一个特定日期的值,你必须使用这个笨重的位置操作符$。这适用于一系列对象,但对于进一步嵌套的任何事情都会失败。

其他问题

一个与上述两种方法的问题是数据的长期增长。当您扩大对象大小时,它将占用磁盘和内存中的更多空间。如果您有一个具有两年价值数据的对象,那么需要将整个700个项目的阵列存储在内存中供您更新今天的数据。这可能不是您具体数据的问题,但应该考虑。

同样,MongoDB查询总是返回顶级对象。同样,如果您有700个项目的数组,您将为每个匹配的文档获取所有项目。有许多方法可以过滤掉返回的字段,但它们不适用于“对象数组”。

+0

'如果你有一个具有两年价值数据的对象,那么需要在整个数组中有700个项目在内存中供你更新今天的数据 - 如果我使用'$ slice'去除子集数组和'$ push'来追加一个新项目到数组? – 2012-03-01 09:37:08

+0

因此,这适用于返回数据,但仅限于按日期顺序推送。但是,在服务器端,即使只传递给它一部分,仍然需要将整个对象拉入内存。 – 2012-03-02 02:00:53

+0

哦,对了,我没有意识到,我觉得它足够聪明,只能删除指定的子集。这对我目前的项目来说是一个破坏者,谢谢你阻止我在6个月内完成任务,然后意识到它! – 2012-03-02 08:38:16