次の行を含む小さなjsonファイルがあります。
{
"IdTitulo": "Jaws",
"IdDirector": "Steven Spielberg",
"IdNumber": 8,
"IdDecimal": "2.33"
}
Test_decという名前のスキーマが私のdbコレクションにあります。これは私がスキーマを作成するために使用したものです:
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")
それらのどれも動作しません。 2つ目は、MongoDBのマニュアル(mongodb-extended-json)によって提供される正式なソリューションであり、エラーは私が私の質問に入力した出力です:bson.errors.InvalidDocument:key 。
現在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')のようなものを解析しようとすると、jsonの形式が無効なため、出力は「ValueError:JSONオブジェクトをデコードできませんでした」になります。
結果として
db.other_col.insert_one(load_raw)
「テスト」の内容が挿入されているということです。しかし、私はdoc_dataをRawBSONDocumentで使用することはできません。それは言う:
TypeError: unpack_from() argument 1 must be string or buffer, not list:
RawBSONDocumentにjsonを直接解析できたとき、すべてのゴミがあり、データベースのレコードは次のサンプルのようになります。
{
"_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にロードするのはそれほど簡単ではないようです。拡張バージョンは、スキーマ検証を使用したいためです。
Olegはそれが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"}
}
最後に、私はソリューションを手に入れました、そしてそれはRawBSONDocumentを使用しています。
最初にjsonファイル:
{
"IdTitulo": "Dead Snow",
"IdDirector": "Tommy Wirkola",
"IdNumber": 11,
"IdDecimal": {"$numberDecimal": "2.22"}
}
&検証スキーマファイル:
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"
}
}
}}
})
したがって、この場合のコレクションは「test_dec」です。
そして、pythonスクリプトは、ファイル「.json」を開き、それを読み取って解析し、MongoDBにインポートされます。
import json
from bson.raw_bson import RawBSONDocument
from pymongo import MongoClient
import bsonjs
#connection
client = MongoClient('localhost',27018)
db = client['movieDB']
coll = db['test_dec']
#open an read file
with open('1.json', 'r') as jfile:
data = jfile.read()
loaded = json.loads(data)
dumped = json.dumps(loaded, indent=4)
bson_bytes = bsonjs.loads(dumped)
coll.insert_one(RawBSONDocument(bson_bytes))
client.close()
挿入されたドキュメント:
{
"_id" : ObjectId("5eb971ec6fbab859dfae8a6f"),
"IdTitulo" : "Dead Snow",
"IdDirector" : "Toomy Wirkola",
"IdDecimal" : NumberDecimal("2.22"),
"IdNumber" : 11
}
フィールドIdDecimalとIdNumberがどのように反転したかはわかりませんが、検証に合格し、本当に満足しています。
NumberDecimalの数値の代わりに「hello」を使用してドキュメントを試しましたが、挿入によって次の結果が得られました。
{
"_id" : ObjectId("5eb973b76fbab859dfae8ecd"),
"IdTitulo" : "Shining",
"IdDirector" : "Stanley Kubrick",
"IdDecimal" : NumberDecimal("NaN"),
"IdNumber" : 19
}
助けてくれたすべてに感謝します。特にオレグ!!!とても我慢していただきありがとうございます。
bson.decimal128.Decimal128 を使用できませんか?何か不足していますか?
from pymongo import MongoClient
from bson.decimal128 import Decimal128
db = MongoClient()['mydatabase']
data = {
"IdTitulo": "Jaws",
"IdDirector": "Steven Spielberg",
"IdNumber": 8,
"IdDecimal": "2.33"
}
data['IdDecimal'] = Decimal128(data['IdDecimal'])
db.other_col.insert_one(data)
タイプ情報を持つ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に挿入するには、 pymongo tutorial に従ってください:
from pymongo import MongoClient
client = MongoClient('localhost', 14420)
db = client.test_database
collection = db.test_collection
collection.insert_one(doc)
print(doc)