mongodb字段的奇怪行为以$开头

时间:2012-01-24 08:59:56

标签: exception mongodb special-characters

在这篇文章MongoDB finding nested elements上,作者声称mongodb文档结构是

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

当我试图重现这个问题时,我遇到了mongodb插入的一些奇怪的行为

在上面的示例数据上运行插入时,我收到了以下错误

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

它表示字段名称不能以$开头。

如果是这种情况,如果我从oid中移除$并留下剩余的$ref& $id未触及

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

令人惊讶的是它起作用了。现在它接受以$

开头的字段

此外,当我尝试此查询时

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

我收到了错误。

我不明白是什么原因造成的?任何人都有一个清晰的想法?

2 个答案:

答案 0 :(得分:4)

$id$refdbrefs使用的特殊标识符。否则,不允许以$开头的字段名称。

但是,您的第一级文档本身不能是dbref,因此错误“要插入的文档不能包含$ fields”。

但是,允许dbrefs作为子文档,例如(来自official docs

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

现在$oid不是特殊标识符,因为$具有特殊语义而不被允许:想想$inc。这是一个运算符,但如果允许$字段名称,它也可以是字段的名称。

使用positional operator in updates

时必须小心
  

位置运算符不能与upsert组合,因为它需要匹配的数组元素。如果您的更新导致插入,则“$”将字面上用作字段名称。

答案 1 :(得分:1)

$ref $id$db是唯一以美元符号开头的有效密钥 - 它们与DBRef约定相关。

您无法使用以美元符号开头的自己的密钥的原因是因为它有Special meaning,否则会造成歧义。