bson.errors.InvalidDocument: ключ '$ numberDecimal' не должен начинаться с '$' при использовании json - PullRequest
2 голосов
/ 29 апреля 2020

У меня есть небольшой json файл со следующими строками:

{
    "IdTitulo": "Jaws",
    "IdDirector": "Steven Spielberg",
    "IdNumber": 8,
    "IdDecimal": "2.33"
}

В моей базе данных есть схема с именем test_de c. Вот что я использовал для создания схемы:

db.createCollection("test_dec",
{validator: {
    $jsonSchema: {
         bsonType: "object",
         required: ["IdTitulo","IdDirector"],
         properties: {
         IdTitulo: {
                "bsonType": "string",
                "description": "string type, nombre de la pelicula"
            },
         IdDirector: {
                "bsonType": "string",
                "description": "string type, nombre del director"
            },
        IdNumber : {
                "bsonType": "int",
                "description": "number type to test"
            },
        IdDecimal : {
                 "bsonType": "decimal",
                 "description": "decimal type"
                    }
       }
    }}
    })

Я сделал несколько попыток вставить данные. Проблема в значении поля IdDecimal.

Некоторые из испытаний, заменяющие строку IdDecimal на:

 "IdDecimal": 2.33

 "IdDecimal": {"$numberDecimal": "2.33"}

 "IdDecimal": NumberDecimal("2.33")

Ни одно из них не работает. Второе - формальное решение, предоставленное руководствами MongoDB (mongodb-extended- json), и ошибка - вывод, который я поместил в своем вопросе: bson.errors.InvalidDocument: ключ '$ numberDecimal' не должен начинаться с ' $ '.

В настоящее время я использую python для загрузки json. Я играл с этим файлом:

import os,sys
import re
import io
import json
from pymongo import MongoClient
from bson.raw_bson import RawBSONDocument
from bson.json_util import CANONICAL_JSON_OPTIONS,dumps,loads
import bsonjs as bs

#connection
client = MongoClient('localhost',27018,document_class=RawBSONDocument)
db     = client['myDB']
coll   = db['test_dec']   
other_col = db['free']                                                                                        

for fname in os.listdir('/mnt/win/load'):                                                                               
    num = re.findall("\d+", fname)

    if num:

       with io.open(fname, encoding="ISO-8859-1") as f:

            doc_data = loads(dumps(f,json_options=CANONICAL_JSON_OPTIONS))

            print(doc_data) 

            test = '{"idTitulo":"La pelicula","idRelease":2019}'
            raw_bson = bs.loads(test)
            load_raw = RawBSONDocument(raw_bson)

            db.other_col.insert_one(load_raw)


client.close()

Я использую файл json. Если я попытаюсь проанализировать что-то вроде Decimal128 ('2.33'), вывод будет "ValueError: нет JSON объект может быть декодирован", потому что мой json имеет недопустимый формат.

Результат

    db.other_col.insert_one(load_raw) 

Это содержание "test" вставлено. Но я не могу использовать doc_data с RawBSONDocument, потому что это так. Там написано:

  TypeError: unpack_from() argument 1 must be string or buffer, not list:

Когда мне удается проанализировать json непосредственно в RawBSONDocument, я получил весь тра sh внутри, и запись в базе данных выглядит как пример здесь:

   {
    "_id" : ObjectId("5eb2920a34eea737626667c2"),
    "0" : "{\n",
    "1" : "\t\"IdTitulo\": \"Gremlins\",\n",
    "2" : "\t\"IdDirector\": \"Joe Dante\",\n",
    "3" : "\t\"IdNumber\": 6,\n",
    "4" : "\"IdDate\": {\"$date\": \"2010-06-18T:00.12:00Z\"}\t\n",
    "5" : "}\n"
     }

Кажется, не так просто загрузить расширенный json в MongoDB. Расширенная версия объясняется тем, что я хочу использовать проверку схемы.

Олег указал, что это NumberDecimal, а не NumberDecimal, как у меня было раньше. Я исправил файл json, но ничего не изменилось.

Выполнено:

with io.open(fname, encoding="ISO-8859-1") as f:
      doc_data = json.load(f)                
      coll.insert(doc_data)

И файл json:

 {
    "IdTitulo": "Gremlins",
    "IdDirector": "Joe Dante",
    "IdNumber": 6,
    "IdDecimal": {"$numberDecimal": "3.45"}
 }

1 Ответ

0 голосов
/ 29 апреля 2020

JSON с информацией о типе называется Extended JSON. Следуя примерам, создайте расширенный json для своих данных:

ext_json = '''
{
    "IdTitulo": "Jaws",
    "IdDirector": "Steven Spielberg",
    "IdNumber": 8,
    "IdDecimal": {"$numberDecimal":"2.33"}
}
'''

В Python, используйте json_util для загрузки расширенного json в словарь Python:

from bson.json_util import loads

doc = loads(ext_json)

print(doc)

# {u'IdTitulo': u'Jaws', u'IdDirector': u'Steven Spielberg', u'IdDecimal': Decimal128('2.33'), u'IdNumber': 8}

Результат этой загрузки иногда упоминается как «документ BSON», но это не BSON, который является двоичным. «BSON» в этом контексте действительно означает, что некоторые значения не относятся к python стандартным типам библиотек. Часть «документ» в основном означает, что объект является словарем.

Вы заметите, что IdNumber имеет нестандартный тип библиотеки:

print type(doc['IdDecimal'])

# <class 'bson.decimal128.Decimal128'>

Чтобы вставить этот словарь в MongoDB, выполните pymon go учебник :

from pymongo import MongoClient
client = MongoClient('localhost', 14420)

db = client.test_database

collection = db.test_collection

collection.insert_one(doc)

print(doc)
...