Странное поведение с полями mongodb начинается с $ - PullRequest
5 голосов
/ 24 января 2012

В этом посте MongoDB находит вложенные элементы , автор утверждает, что структура документа 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 ]

4 голосов
/ 24 января 2012

$id и $ref - специальные идентификаторы, используемые для dbrefs . В противном случае имена полей, начинающиеся с $, не допускаются.

Однако ваш документ первого уровня не должен быть сам по себе dbref, поэтому ошибка «документ для вставки не может иметь $ полей».

Однако в качестве вложенных документов допускается использовать dbref, например (из официальных документов )

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

Теперь $oid не является специальным идентификатором и не допускается, потому что $ имеет особую семантику: представьте себе $inc. Это оператор, но если разрешено $ имен полей, это также может быть имя поля.

Будьте осторожны при использовании позиционного оператора в обновлениях :

Позиционный оператор не может быть объединен с upsert, так как он требует соответствующего элемента массива. Если ваше обновление приводит к вставке, то «$» будет буквально использоваться в качестве имени поля.

1 голос
/ 24 января 2012

$ref $id и $db являются единственными действительными ключами, которые начинаются со знака доллара - они относятся к соглашению DBRef .

Причина, по которой вы можете 'Используйте свои собственные ключи, начинающиеся со знака доллара, потому что он имеет Специальный , означающий , и в противном случае создаст двусмысленность.

...