You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过MongoEngine批量导入JSON数据至MongoDB?

使用MongoEngine批量导入DataFrame数据到MongoDB的问题及解决方法

问题背景

尝试将Pandas DataFrame中的大量数据通过MongoEngine导入MongoDB,先将DataFrame转为JSON格式,执行导入时出现TypeError: __main__.MarketData() argument after ** must be a mapping, not str错误。

现有代码及问题

1. DataFrame转JSON代码

result = df.to_json(orient="index")
parsed = json.loads(result)
json_data = json.dumps(parsed, indent=4) 

2. JSON格式化代码

json_object = json.loads(json_data)
json_formatted_str = json.dumps(json_object, indent=2)
print(json_formatted_str)

得到的JSON结构:

{
  "0": {
    "Address": " Bursvej 30 ",
    "Zip/city": "4930 Maribo",
    "Price": " 148.000kr. ",
    "Date": 1673371545635
  },
  "1": {
    "Address": " Garrdesmuttevej 20 ",
    "Zip/city": "9550 Mariager",
    "Price": " 148.000kr. ",
    "Date": 1673371545635
  },
  "2": {
    "Address": " Norrevej 21 ",
    "Zip/city": "6990 Ulfborg",
    "Price": " 150.000kr. ",
    "Date": 1673371545635
  }
}

3. 导入代码及错误

MD = [MarketData(**data) for data in json_formatted_str]
MarketData.objects.insert(MD, load_bulk=False)

错误信息:TypeError: __main__.MarketData() argument after ** must be a mapping, not str

4. DataFrame示例

Address               Zip/city        Price               Date
0   Bursøvej 30, Bursø    4930 Maribo    148.000 kr.    2023-01-10 17:25:45.635483
1   Gærdesmuttevej 20     9550 Mariager   148.000 kr.    2023-01-10 17:25:45.635483
2   Nørrevej 21           6990 Ulfborg    150.000 kr.    2023-01-10 17:25:45.635483
3   Egernvænget 54        4733 Tappernøje 195.000 kr.    2023-01-10 17:25:45.635483
4   Egernvænget 56        4733 Tappernøje 195.000 kr.    2023-01-10 17:25:45.635483

5. MarketData模型代码

class MarketData(Document):
    #answers = DictField()
    Address = DynamicField(required=False)
    city = DynamicField(required=False)
    Price = DynamicField(required=False)
    date = DynamicField(required=False)
    
    def json(self):
        market_dict = {
            "username": self.username,
            "city": self.city,
            "Price": self.price
        }
        return json.dumps(market_dict)

问题原因

错误的核心是json_formatted_str是字符串类型,遍历字符串会得到单个字符,导致MarketData(**data)中的data是单个字符而非字典映射。另外,现有代码存在冗余的JSON序列化/反序列化步骤,且DataFrame字段与模型字段不完全匹配(如模型中的city对应DataFrame的Zip/city,date对应Date)。

解决方法

方法一:直接从DataFrame生成MongoEngine对象列表(推荐)

跳过冗余的JSON转换步骤,直接从DataFrame的行数据生成对象:

# 处理DataFrame字段与模型字段的映射
records = df.to_dict('records')
processed_records = []
for record in records:
    processed = {
        "Address": record["Address"],
        "city": record["Zip/city"],  # 匹配模型中的city字段
        "Price": record["Price"],
        "date": record["Date"]  # 匹配模型中的date字段
    }
    processed_records.append(processed)

# 批量创建对象并插入
MD = [MarketData(**data) for data in processed_records]
MarketData.objects.insert(MD, load_bulk=False)

方法二:修复JSON转换后的遍历逻辑

如果坚持使用JSON转换,需遍历json_object的值而非格式化后的字符串:

result = df.to_json(orient="index")
json_object = json.loads(result)

# 遍历json_object的values(),每个value是一条数据字典
MD = [MarketData(**{
    "Address": item["Address"],
    "city": item["Zip/city"],
    "Price": item["Price"],
    "date": item["Date"]
}) for item in json_object.values()]

MarketData.objects.insert(MD, load_bulk=False)

额外优化:模型字段规范

建议将模型字段改为更匹配数据类型的字段(而非全部用DynamicField),例如:

from mongoengine import StringField, DateTimeField, FloatField

class MarketData(Document):
    Address = StringField(required=False)
    city = StringField(required=False)
    Price = FloatField(required=False)  # 可先处理Price字符串转数值
    date = DateTimeField(required=False)
    
    # 可选:移除无用的json方法(或修正字段名错误)
    def json(self):
        market_dict = {
            "Address": self.Address,
            "city": self.city,
            "Price": self.Price,
            "date": self.date.isoformat() if self.date else None
        }
        return json.dumps(market_dict)

批量插入的性能优化

对于大量数据,推荐使用insert_many(MongoEngine支持):

# 使用insert_many更高效
MarketData.objects.insert_many(processed_records, load_bulk=False)

总结

无需转回PyMongo,MongoEngine完全支持批量导入。核心问题是错误地遍历了JSON字符串而非字典对象,同时需注意DataFrame字段与模型字段的映射匹配。直接从DataFrame生成字典列表是最简洁高效的方式。

内容的提问来源于stack exchange,提问作者jmChrist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:35:20