【问题标题】:MongoDB - Is it possible to query by associative array key?MongoDB - 是否可以通过关联数组键查询?
【发布时间】:2012-02-29 20:49:38
【问题描述】:

我需要存储一些数据,这些数据本质上只是日期/整数的键值对数组,其中日期始终是唯一的。

我希望能够像关联数组一样存储它:

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),
)

显然前者更加简洁明了,但我是否能够以我想要的方式查询它,如果没有,是否还有其他更合适的模式?

【问题讨论】:

标签: php mongodb mongodb-php


【解决方案1】:

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

方法 #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 个项目的数组,您将获得每个匹配的文档的所有项目。有一些方法可以过滤掉返回的字段,但它们不适用于“对象数组”。

【讨论】:

  • If you have an object with two years worth of data that entire array of 700 items will need to be in memory for you to update data for today - 如果我要使用 $slice 删除数组的子集并使用 $push 将新项目附加到数组中呢?
  • 所以这适用于返回数据,但前提是您按日期顺序推送。但是,在服务器端,它仍然需要将整个对象拉入内存,即使它只传递了一部分。
  • 哦,对了,我没有意识到这一点,我认为它足够聪明,只删除指定的子集。对于我当前的项目来说,这有点破坏交易,感谢您阻止我在 6 个月后实现这一目标!
  • 是的,这是 BSON 格式创建方式的副作用。它非常串行,因此需要“从前到后”读取块才能正确反序列化对象。
猜你喜欢
  • 2015-10-19
  • 2016-01-31
  • 2021-12-12
  • 2011-08-14
  • 2016-08-10
  • 2017-09-05
  • 1970-01-01
  • 1970-01-01
  • 2020-01-09
相关资源
最近更新 更多