Arrays 任意数组位置的MongoDB增量

Arrays 任意数组位置的MongoDB增量,arrays,mongodb,increment,Arrays,Mongodb,Increment,我想使用数组作为与此文档关联的文档的计数器。每个数组元素对应一个文档,该数组中的数字对应于该文档的某些数据段。这些数字不与其关联文档一起存储,因此可以对“主”文档的字段以及“关联”文档数组中的数据执行查询 由于$inc和数组初始化的变幻莫测,似乎无法做到这一点: > use foo switched to db foo > db.foo.save({id: []}) > db.foo.update({}, {$inc: {'id.4': 1}}) > db.foo.fin

我想使用数组作为与此文档关联的文档的计数器。每个数组元素对应一个文档,该数组中的数字对应于该文档的某些数据段。这些数字不与其关联文档一起存储,因此可以对“主”文档的字段以及“关联”文档数组中的数据执行查询

由于$inc和数组初始化的变幻莫测,似乎无法做到这一点:

> use foo
switched to db foo
> db.foo.save({id: []})
> db.foo.update({}, {$inc: {'id.4': 1}})
> db.foo.find().pretty()
{
    "_id" : ObjectId("5279b3339a056b26e64eef0d"),
    "id" : [
        null,
        null,
        null,
        null,
        1
    ]
}
> db.foo.update({}, {$inc: {'id.2': 1}})
Cannot apply $inc modifier to non-number
是否有某种方法可以递增null或用零初始化数组


另一种方法是以键/值格式存储数组值,因此它将是一个稀疏数组,但无法向上插入到数组中,这使得该方法不可行。

虽然我不赞成可能无限大小的数组,但有一个技巧可以让您在这里做正确的事情:

db.foo.insert({id:[]})
每当在索引N处递增计数器时,请确保将所有索引递增0至N

db.foo.update({}, {$inc: {'id.0':0, 'id.1':0, 'id.2':0, 'id.3':0, 'id.4':1 } })
db.foo.update({}, {$inc: {'id.0':0, 'id.1':0, 'id.2':1 } })
db.foo.find()
{ "_id" : ObjectId("5279c8de0e05b308d0cf21ca"), "id" : [  0,  0,  1,  0,  1 ] }

您知道阵列的大小吗?不幸的是,不知道。理论上它可以无限扩展,尽管实际上它可能限制在1000左右,但分布将强烈地向1倾斜,当前平均值为~3。每个对象只需预初始化4kB,但可能有数百万或数十亿个这样的对象,因此它开始累积。如果您认为它们可以无限增长,将它们放在一个数组中不是一个好主意-您的文档大小将不断增长,这对性能不利。同时,有一个技巧可以按原样使用。{$inc:{'id.0':0,'id.1':0,'id.2':0,'id.3':1}}将生成一个数组id:[0,0,0,1],如果它不存在,则将增加第4个元素$inc by 0是一个不可操作的选项,但它将为您做正确的事情,id:[]重新性能,这是事实,但我预计99.9%的情况下阵列不会特别大。除非有人滥用这个系统,否则我无法想象这个用例会超过1000个。然而,事实证明,每次创建“关联”文档时,我都可以在数组上加上一个零,而不会引起额外的DB写入,这也起到了作用。我应该早就想到了。我喜欢复杂而直接的正向解决方案——这个解决方案的优点是一次增加数组N个元素……如果我已经在写入几个文档字段,这会对性能产生显著影响吗?在我的解决方案中,每次创建新的关联文档时,我都会$push到主文档中的数组上,以及对主文档的其他写入。在您的方案中,我只根据需要创建数组条目,但可能会执行更多的无操作增量。我对mongoguts的了解还不足以说明哪一个更好,从性能上看。没有ops的好处是它们。。。无操作:)它们应该几乎是免费的。现在添加新字段会使文档增长,因此偶尔会因为需要为其分配更多空间而减慢速度。考虑UpEWOWER SOF2的大小,以使该集合的影响最小化。