我正在尝试使用PyMongo将文档(在本例中为twitter信息)插入Mongo数据库。
如下所示,tweets_listdt [0]与
完全相同{
'created_at': u'Sun Aug 03 17:07:24 +0000 2014',
'id': 2704548373,
'name': u'NoSQL',
'text': u'RT @BigdataITJobs: Data Scientist \u2013 Machine learning, Python, Pandas, Statistics @adam_rab in London, United Kingdom http://t.co/pIIJVPCuN8\u2026'
}
但我无法将tweets_listdt [0]保存到我的Mongodb中,而我可以使用后者保存。
In[529]: tweets_listdt[0] == {'created_at': u'Sun Aug 03 17:07:24 +0000 2014',
'id': 2704548373,
'name': u'NoSQL',
'text': u'RT @BigdataITJobs: Data Scientist \u2013 Machine learning, Python, Pandas, Statistics @adam_rab in London, United Kingdom http://t.co/pIIJVPCuN8\u2026'}
Out[528]: **True**
这个失败了:
In[530]: tweetsdb.save(tweets_listdt[0])
tweetsdb.save({'created_at': u'Sun Aug 03 17:07:24 +0000 2014',
'id': 2704548373,
'name': u'NoSQL',
'text': u'RT @BigdataITJobs: Data Scientist \u2013 Machine learning, Python, Pandas, Statistics @adam_rab in London, United Kingdom http://t.co/pIIJVPCuN8\u2026'})
Traceback (most recent call last):
File "D:\Program Files\Anaconda\lib\site-packages\IPython\core\interactiveshell.py", line 3035, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-529-b1b81c04d5ad>", line 1, in <module>
tweetsdb.save(tweets_listdt[0])
File "D:\Program Files\Anaconda\lib\site-packages\pymongo\collection.py", line 1903, in save
check_keys, manipulate, write_concern)
File "D:\Program Files\Anaconda\lib\site-packages\pymongo\collection.py", line 430, in _insert
gen(), check_keys, self.codec_options, sock_info)
InvalidDocument: **Cannot encode object: 2704548373**
这个没问题:
In[531]: tweetsdb.save({'created_at': u'Sun Aug 03 17:07:24 +0000 2014',
'id': 2704548373,
'name': u'NoSQL',
'text': u'RT @BigdataITJobs: Data Scientist \u2013 Machine learning, Python, Pandas, Statistics @adam_rab in London, United Kingdom http://t.co/pIIJVPCuN8\u2026'})
Out[530]: **ObjectId('554b38d5c3d89c09688b1149')**
感谢伯尼。我使用的PyMongo版本是3.0.1。
这里是对id的数据类型的检查:
In[36]:type(tweets_listdt[0]['id'])
Out[37]:long
如果我只是使用:
for tweet in tweets_listdt:
tweetsdb.save(tweet)
上述错误会发生。
但如果我加上这一行,一切都还可以:
tweet['id'] = int(tweet['id'])
当我直接分配
tweets_listdtw = {'created_at': u'Sun Aug 03 17:07:24 +0000 2014',
'id': 2704548373,
'name': u'NoSQL',
'text': u'RT @BigdataITJobs: Data Scientist'}
tweetsdb.save(tweets_listdtw)正在运作,
print type(tweets_listdtw['id'])
<type 'numpy.int64'>
再次感到困惑...所以绝对长型是好的......但是为什么在我改变了#id;&#39;进入int,节约是否有效?
答案 0 :(得分:9)
您的问题是numpy.int64
对MongoDB来说是陌生的。我曾经也有过一样的问题。
解决方案是将违规值转换为MongoDB将理解的数据类型,这里是我在代码中转换这些违规值的示例:
try:
collection.insert(r)
except pymongo.errors.InvalidDocument:
# Python 2.7.10 on Windows and Pymongo are not forgiving
# If you have foreign data types you have to convert them
n = {}
for k, v in r.items():
if isinstance(k, unicode):
for i in ['utf-8', 'iso-8859-1']:
try:
k = k.encode(i)
except (UnicodeEncodeError, UnicodeDecodeError):
continue
if isinstance(v, np.int64):
self.info("k is %s , v is %s" % (k, v))
v = int(v)
self.info("V is %s" % v)
if isinstance(v, unicode):
for i in ['utf-8', 'iso-8859-1']:
try:
v = v.encode(i)
except (UnicodeEncodeError, UnicodeDecodeError):
continue
n[k] = v
collection.insert(n)
我希望这会对你有所帮助。
答案 1 :(得分:3)
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, numpy.integer):
return int(obj)
elif isinstance(obj, numpy.floating):
return float(obj)
elif isinstance(obj, numpy.ndarray):
return obj.tolist()
else:
return super(CustomEncoder, self).default(obj)
data_dict_1 = json.dumps(data_dict,cls=CustomEncoder)
data_dict_final = json.loads(data_dict_1)
答案 2 :(得分:0)
我非常喜欢奥兹的答案。用python 3扩展它:
def correct_encoding(dictionary):
"""Correct the encoding of python dictionaries so they can be encoded to mongodb
inputs
-------
dictionary : dictionary instance to add as document
output
-------
new : new dictionary with (hopefully) corrected encodings"""
new = {}
for key1, val1 in dictionary.items():
# Nested dictionaries
if isinstance(val1, dict):
val1 = correct_encoding(val1)
if isinstance(val1, np.bool_):
val1 = bool(val1)
if isinstance(val1, np.int64):
val1 = int(val1)
if isinstance(val1, np.float64):
val1 = float(val1)
new[key1] = val1
return new
它对那些嵌套文档具有递归性,我认为python 3将所有字符串存储为unicode,因此我删除了编码部分。
答案 3 :(得分:0)
我尝试使用愚蠢的解决方案,但是它可以工作。.假设x
是numpy.int32
或numpy.int64
类型的变量。 / p>