user85461
user85461

Reputation: 6690

$set operator interpreting array index as object index in mongodb

MongoDB seems to interpret $set paths with numerical components as object keys rather than array indexes if the field has not already been created as an array.

> db.test.insert({_id: "one"});
> db.test.update({_id: "one"}, {$set: {"array.0.value": "cheese"}});
> db.find({_id: "one"})
{ "_id": "one", "array": { "0" : { "value" : "cheese" } }

I expected to get "array": [{"value": "cheese"}], but instead it was initialized as an object with a key with the string "0".

I could get an array by initializing the whole array, like so:

> db.test.update({_id: "one"}, {$set: {"array": [{"value": "cheese"}]}});

... but this would clobber any existing properties and other array elements that might have been previously set.

Is there any way to convince $set that I want "array" to be an array type, with the following constraints:

  1. I want to execute this in a single query, without looking up the record first.
  2. I want to preserve any existing array entries and object values

In short, I want the behavior of $set: {"array.0.value": ... } if "array" had already been initialized as an array, without knowing whether or not it has. Is this possible?

Upvotes: 0

Views: 50

Answers (1)

jpaljasma
jpaljasma

Reputation: 1612

I am not sure if this is possible without lookup. Perhaps you can change schema design, and try something like this:

db.test.insert({_id: "one"});
db.test.update({_id: "one"}, {$addToSet: {array: { $each:['cheese', 'ham'] }}});
db.test.findOne({_id:'one'});
// { "_id" : "one", "array" : [  "cheese",  "ham" ] }

Handling array elements (sub-documents in array) in MongoDb is pain. https://jira.mongodb.org/browse/SERVER-1243

Upvotes: 1

Related Questions