tags:

views:

35

answers:

1

I'm developing a webapp which has a portal-ish component to it (think like multiple panels that can be drug around from column to column and added or removed). I'm using MongoDB to store this info with a format like so...

{
    _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 ...
        }
    ]
}

I'm attempting to use atomic/modifier operations with update() and this is getting confusing. If I wanted to just update one property of a specific panel, how do I reference that?

update(
    { _id: ObjectId(...) },
    { $set: { columns.[???].panels.[???].top: 500 }
)
A: 

If you know the index in the array you can access the array element directly using dot notation.

update(
{ _id: ObjectId(xxxx) },
{ $set: { 'columns.0.panels.0.top' : 125}}
)

Make sure you encase the dot notated path in quotes as a string.

Edit:

To give more detail on how this could work dynamically, I'll give an example in PHP:

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

Yes there is the positional operator, but it does not appear to be advanced enough to change arrays within arrays, this may change in MongoDB 1.7.0

There is an alternative you can do instead of trying to stuff this information into a nested document. Try to flatten it out. You can create a collection that has panel & column objects:

column object:

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

panel object:

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

Then you can find all columns that belong to a user by doing:

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

You can find all panels for a specific column by doing:

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

Since each column and panel will have a unique ID given by MongoDB to it, you can easily query and atomically set options.

update({'_id': ObjectId('idstring')}, {$set : { 'top' : 125}});
Klinky
I'm wondering this too. Hard-coding the indexes really isn't that feasible. Still trying to figure out how to use the positional operator http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator
Dex
added more detail
Klinky