Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird behavior with mongodb fields start with $

On this post MongoDB finding nested elements, author claims that the mongodb document structure is

      car : { "$ref" : "cars" , "$id" : { "$oid" : "4e8478ace4b0dea06288ad63"}}

When i tried to reproduce the problem, i encountered some weird behaviors with mongodb insertion

When run the insertion on above sample data, i got following error

> db.sample.insert({car:{ "$ref" : "cars" , "$id" : { "$oid" : "4e8478ace4b0dea06288ad63"}}})
Tue Jan 24 14:09:07 uncaught exception: field names cannot start with $ [$oid]

it says that field names cannot start with $.

If thats the case, it should not work if i remove $ from oid and left the remaining $ref & $id untouched

    > db.sample.insert({car:{ "$ref" : "cars" , "$id" : { "oid" : "4e8478ace4b0dea06288ad63"}}})
    > db.sample.find()
{ "_id" : ObjectId("4f1e6fbc403aae757ec6dea5"), "car" : { "$ref" : "cars", "$id" : { "oid" : "4e8478ace4b0dea06288ad63" } } }

surprisingly it worked. Now it accepts the fields start with $

Also when i tried this query

> db.sample.insert({ "$ref" : "cars" })
document to insert can't have $ fields

i got the error back.

I don't understand what causes this? anybody have a clear idea?

like image 412
RameshVel Avatar asked Jan 24 '12 08:01

RameshVel


2 Answers

$id and $ref are special identifiers used for dbrefs. Otherwise, field names starting with a $ aren't allowed.

However, your first-level document must not be a dbref itself, hence the error "document to insert can't have $ fields".

However, dbrefs are allowed as subdocuments, e.g. (from the official docs)

"name" : "Joe",
"classes" : [
        {
                "$ref" : "courses",
                "$id" : ObjectId("4b0552b0f0da7d1eb6f126a1")
        }
]

Now $oid is not a special identifier, and is not allowed because the $ has special semantics: Think of $inc. That is an operator, but if $ field names were allowed, it could also be the name of a field.

You have to be careful when using the positional operator in updates:

The positional operator cannot be combined with an upsert since it requires a matching array element. If your update results in an insert then the "$" will literally be used as the field name.

like image 68
mnemosyn Avatar answered Oct 18 '22 22:10

mnemosyn


$ref $id and $db are the only valid keys which begin with a dollar sign - they are related to the DBRef convention.

The reason you can't use your own keys starting with a dollar sign is becuase it has Special meaning and would otherwise create ambiguity.

like image 20
AD7six Avatar answered Oct 18 '22 22:10

AD7six