Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB:如果使用$addToSet或$push,是否应该预分配文档?_Mongodb_Meteor - Fatal编程技术网

MongoDB:如果使用$addToSet或$push,是否应该预分配文档?

MongoDB:如果使用$addToSet或$push,是否应该预分配文档?,mongodb,meteor,Mongodb,Meteor,我一直在研究MongoDB,我知道强烈建议在插入时完全构建(预先分配)文档结构,这样以后对该文档的更改就不需要在磁盘上移动文档。使用$addToSet或$push时是否适用 例如,假设我有以下文档: "_id" : "rsMH4GxtduZZfxQrC", "createdAt" : ISODate("2015-03-01T12:08:23.007Z"), "market" : "LTC_CNY", "type" : "recentTrades", "data" : [ {

我一直在研究MongoDB,我知道强烈建议在插入时完全构建(预先分配)文档结构,这样以后对该文档的更改就不需要在磁盘上移动文档。使用$addToSet或$push时是否适用

例如,假设我有以下文档:

"_id" : "rsMH4GxtduZZfxQrC",
"createdAt" : ISODate("2015-03-01T12:08:23.007Z"),
"market" : "LTC_CNY",
"type" : "recentTrades",
"data" : [ 
    {
        "date" : "1422168530",
        "price" : 13.8,
        "amount" : 0.203,
        "tid" : "2435402",
        "type" : "buy"
    }, 
    {
        "date" : "1422168529",
        "price" : 13.8,
        "amount" : 0.594,
        "tid" : "2435401",
        "type" : "buy"
    }, 
    {
        "date" : "1422168529",
        "price" : 13.79,
        "amount" : 0.594,
        "tid" : "2435400",
        "type" : "buy"
    }
]
我正在使用以下命令之一将新的对象数组(
newData
)添加到
data
字段:

$addToSet要添加到数组末尾:

Collection.update(
  { _id: 'rsMH4GxtduZZfxQrC' },
  {
    $addToSet: {
      data: {
        $each: newData
      }
    }
  }
);
Collection.update(
  { _id: 'rsMH4GxtduZZfxQrC' },
  {
    $push: {
      data: {
        $each: newData,
        $position: 0
      }
    }
  }
);
要添加到阵列前端的$push(带$position):

Collection.update(
  { _id: 'rsMH4GxtduZZfxQrC' },
  {
    $addToSet: {
      data: {
        $each: newData
      }
    }
  }
);
Collection.update(
  { _id: 'rsMH4GxtduZZfxQrC' },
  {
    $push: {
      data: {
        $each: newData,
        $position: 0
      }
    }
  }
);
由于从
newData
添加了新对象,文档中的
data
数组将增长。那么,这种类型的文档更新会导致文档在磁盘上移动吗


对于这个特定的系统,这些文档中的
数据
数组在中可以增长到75k个以上的对象,因此,如果这些文档在每次$addToSet或$push更新后确实在磁盘上移动,那么文档在插入时是否应该定义75k个null(
数据:[null,null…null]
),然后可能会使用$set来替换随时间变化的值?谢谢

MongoDB使用两种分配策略的威力来存储文档,这意味着它将分配文档^2的大小以进行存储。因此,如果嵌套数组的总增长量不超过原始大小的2倍,mongo就不必重新分配文档


请参阅:

这里的底线是,任何“文档增长”几乎总是会导致存储分配的“物理移动”,除非您以某种方式对原始文档提交进行了“预分配”。是的,有“二次幂”分配,但这并不总是意味着对您的存储箱有效

这里的附加“捕获”是打开的,其中“隐藏捕获”实际上是这样的“预分配”方法可能不会“复制”到副本集中的其他成员,如果这些指令不在应用副本集项的“oplog”期间

如果任何结构的增长超出了“初始分配”或可应用的一般技巧所分配的内容,将导致该文档在超出最初提供的空间时在存储空间中“移动”

为了确保不会发生这种情况,您总是“预分配”原始创建数据的预期规定。并对已经描述的情况提出了明显的警告

我知道强烈建议在插入时完全构建(预分配)文档结构,这样以后对该文档的更改就不需要在磁盘上移动文档。使用$addToSet或$push时是否适用

如果它对用例是可行的,则建议使用它,而通常情况下不可行。时间序列数据是一个显著的例外。它实际上不适用于
$addToSet
$push
,因为它们倾向于通过增加数组来增加文档的大小

这些文档中的数据数组可以在

停下来。是否确实要不断增加包含成千上万个条目的数组?您是否要查询想要返回的特定条目?是否要为数组项中的任何字段编制索引?您可能需要重新考虑文档结构。也许您希望每个
数据
条目都是一个单独的文档,每个条目中都复制有
市场
类型
创建数据
等字段?您不必担心文档移动

为什么阵列将增长到75K个条目?你能减少每个文档的输入吗?是这个吗?能够使用mmap存储引擎预先分配文档并进行就地更新是很好的,但这并不是每个用例都可行的,MongoDB也不需要这样才能很好地执行

文档是否应该在insert时定义75k个null(数据:[null,null…null]),然后可能使用$set随时间替换这些值

不,这不是很有帮助。文档大小将根据数组中null值的BSON大小来计算,因此当您用另一种类型替换
null
时,该大小将增加,并且您仍将得到文档重写。您需要使用所有字段都设置为其类型的默认值的对象预先分配数组,例如

{
    "date" : ISODate("1970-01-01T00:00:00Z")    // use a date type instead of a string date
    "price" : 0,
    "amount" : 0,
    "tid" : "000000", // assuming 7 character code - strings icky for default preallocation
    "type" : "none"    // assuming it's "buy" or "sell", want a default as long as longest real values
}

您是否建议在插入时使用75k null(
数据:[null,null…null]
)定义文档,然后可能使用$set随时间使用实际对象替换null值?而不是使用$addToSet随时间动态增长文档?这能解决问题吗?谢谢@JonCursi当然,当您提交具有相同“设置”结果的多个值时,这些值将被服务器本身作为
$addToSet
的过程“取消”,因为它们是相同的。但不建议这样做,您可能应该在提交之前在客户机代码中对其进行分类。2分配的威力并不一定能消除阵列增长超过这些长度的问题。最好的情况是评估您的使用模式,并根据需要根据实际的存储需求进行设计/预分配。感谢您的回复,这非常有帮助!是的,这是时间序列数据。我根据新加入的对象(大约1个对象/秒)生成了几个课程解决方案,这些文档就是客户端订阅中使用的文档。但我正试图找出存储原始对象的最佳方式,我只想保留这些对象,以备将来需要它们作为参考,即由于系统故障等原因需要重新生成课程分辨率。存储hundr的最佳方式是什么