如何在MongoDB中设置子子数组项

8

我正在开发一个Web应用程序,其中有一个门户组件(类似于可以从列拖动到列并添加或删除的多个面板)。 我正在使用MongoDB存储此信息,格式如下...

{
    _id: ObjectId(...),
    title: 'My Layout',
    columns: [
        {
            order: 1,
            width: 30,
            panels: [
                { title: 'Panel Title', top: 100, content: '...' },
                { title: 'Panel Title', top: 250, content: '...' },
            ]
        },
        {
            ... multiple columns ...
        }
    ]
}

我正在尝试使用update()的原子/修饰符操作,这让我感到困惑。如果我只想更新特定面板的一个属性,我该如何引用它?

update(
    { _id: ObjectId(...) },
    { $set: { columns.[???].panels.[???].top: 500 }
)
2个回答

16
如果您知道数组中的索引,可以使用点表示法直接访问数组元素。
update(
{ _id: ObjectId(xxxx) },
{ $set: { 'columns.0.panels.0.top' : 125}}
)

确保将以点表示的路径用引号作为字符串括起来。

编辑:

为了更详细地说明如何在动态环境下工作,我将举一个 PHP 的例子:

$action = array("columns.$colNum.panels.$panelNum" => $newValue);

是的,有定位操作符,但它似乎不够先进,无法改变数组中的数组,这可能会在MongoDB 1.7.0中改变。

如果您不想将此信息嵌套到文档中,可以尝试使用另一种替代方法。尝试展平它。您可以创建一个包含面板和列对象的集合:

列对象:

{
_id: // MongoId
type: 'column',
user: 'username',
order: 1,
width: 30,
}

面板对象:

{
_id: //MongoId
type: 'panel',
user: 'username',
parentColumn: //the columns _id string
top: 125,
left: 100
}

然后,您可以通过执行以下操作找到属于用户的所有列:

find({ type: 'column', user:'username'});

你可以通过以下方式找到特定列的所有面板:

find({type: 'panel', columnOwner:'ownerID'});

由于每个列和面板都有 MongoDB 分配的唯一 ID,因此您可以轻松查询并以原子方式设置选项。

update({'_id': ObjectId('idstring')}, {$set : { 'top' : 125}});

我也在思考这个问题。硬编码索引真的不是很可行。仍在努力弄清如何使用位置操作符 http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator - Dex

0

我也遇到过这样的情况,我在 $pull 后使用了 $addToSet 来替换即更新所需内容。

 update(
{ _id: ObjectId(...) },
{ $addToSet: { columns.$.panels : "new sub-Doc" }
)

然后删除旧值

update({_id:ObjectId(....)},{$pull : { columns.$.panels : {"top" : 100} }})

列名前的 $ 符号是什么意思? - Oliver Dixon
"$"作为占位符,在更新操作中用于更新与查询条件匹配的第一个元素。请参考https://docs.mongodb.com/manual/reference/operator/update/positional/#up._S_。 - achuth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接