0

I'm having trouble removing/renaming an array object from my mongodb.

{ 
    "_id" : ObjectId("556a7e1b7f0a6a8f27e01b8a"), 
    "accountid" : "AC654164545", 
    "sites" :[ 
       { "site_id" : "example1.com" }, 
       { "002" : "example2.com" }, 
       { "003" : "example3.com" }, 
       { "004" : "example4.com" }, 
       { "005" : "example5.com" }, 
       { "006" : "example6.com" } 
    ]}
}

Please take notice of the array key "site_id", I want to change it to "001" by either removing and appending it, which I know how to do, or rename it.

I've tried:

db.accounts.update({'id':ObjectId("556a7e1b7f0a6a8f27e01b8a")}, {$unset: {sites.site_id}})

But that says "unexpected token". So I tried:

db.accounts.update({'id':ObjectId("556a7e1b7f0a6a8f27e01b8a")}, {$unset: {sites:site_id}})

That says "site_id is not defined"

Then I tried:

db.accounts.update({'id':ObjectId("556a7e1b7f0a6a8f27e01b8a")}, {$unset: {sites:'site_id'}})

That says WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })

I also tried a $rename command:

db.accounts.update( { _id:ObjectId("556a7e1b7f0a6a8f27e01b8a") }, { $rename: { "sites.site_id": "sites.001" } } )

But that gave me a "Cannot use part (sites of sites.site_id) to traverse the element"

One option would be to use .find(), iterate through and delete it. Save the undeleted ones into an object, and run an .insert() command, but I want to stay away from that if I have too.

David
  • 2,094
  • 3
  • 30
  • 47
  • possible duplicate of [MongoDB rename database field within array](http://stackoverflow.com/questions/9122966/mongodb-rename-database-field-within-array) – Neo-coder Jun 01 '15 at 06:22
  • Not really a duplicate being that the accepted answer says there is no way to do it except for iterating over everything.... and it's from 3 years ago. Tobias provided the correct answer for me, as I needed to use $set instead of $rename or $unset. – David Jun 02 '15 at 01:15

2 Answers2

0

This site talks about dynamic renaming: http://docs.mongodb.org/manual/reference/operator/update/positional/

Aka first you make a matching query and then you use the $ to match that to the index in the array.

Here's the query that'll accomplish what you want for the test data you provided:

db.accounts.update({'accountid':"AC654164545", "sites.site_id": "example1.com"}, {$set: {"sites.$": {'001': 'example1.com'}}})
  • But you _hard-code_ the value. I guess the OP had in mind to copy the existing value. Is it possible that way ? – Sylvain Leroux Jun 01 '15 at 06:38
  • 1
    I'd guess you'd have to use some client-side code to achieve that, as you're not allowed to use $rename on dynamic values (using the `$` selector) + very few update functions available on arrays (http://docs.mongodb.org/manual/reference/operator/update-array/)... Here's another example in the same area and which might be extendable to handle the problem: https://stackoverflow.com/questions/14008856/mongodb-update-trying-to-set-one-field-from-a-property-of-another – Tobias Christensen Jun 01 '15 at 06:54
  • 1
    hard coding was ok. It was easy enough to use an array in it's place to do that bit; `search['sites.' + site_id] = 'example1.com';` – David Jun 02 '15 at 01:17
0

It is not recommended to use dynamic values such as numbers as a key in document structure. This will be more difficult to query using such values.

You can use $set and $elemMatch to get result as following:

db.collection.update({
    '_id': ObjectId("556a7e1b7f0a6a8f27e01b8a"),
    "sites": {
    $elemMatch: {
        "site_id": "example1.com"
    }
    }
  }, {
    $set: {
    "sites.$":{"001": "example1.com"}
    }
})
Vishwas
  • 6,967
  • 5
  • 42
  • 69
  • This didn't work, as it just gave me `WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })`. However it made me think of the $set command which was the answer as shown in Tobias' answer. Thank you! – David Jun 02 '15 at 01:18