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

PyMongo从Python字典向MongoDB存储小数与日期的问题排查

问题解答

1. 日期存储:是否需要转为日期类型?

从你的测试结果能看到:

  • myDateInsertedFmt 是格式化后的字符串,存储为 MongoDB 的字符串类型
  • myDateInsertedNow 是 Python datetime 对象,自动被编码为 MongoDB 的 ISODate 类型

建议优先存储为日期类型,原因:

  • 支持日期范围查询、按日期排序等操作
  • MongoDB 内部以 UTC 存储,自动处理时区转换
  • 避免字符串格式不一致引发的问题

如果需要展示格式化后的日期,可在查询后再做字符串格式化,不必在存储阶段处理。

2. 货币存储:是否必须用浮点型?

不需要。直接用 Python decimal.Decimal 报错,是因为 PyMongo 默认不支持编码该类型,但 MongoDB 提供了 Decimal128 类型,专门用于高精度数值存储,完全适配货币场景(可避免浮点型的精度丢失问题)。

解决方法:

使用 bson.Decimal128 类型转换:

from decimal import Decimal
from bson import Decimal128

row_dict['myCurrencyDecimal'] = Decimal128(Decimal('25.97'))

存储后 MongoDB 会以 Decimal128("25.97") 的形式保存,完美保留精度。

3. 如何处理带引号的数字(JSON/CSV 中的字符串类型数字)

无论是 JSON 中带引号的数字,还是 CSV 解析后得到的字符串型数字,都需要在插入 MongoDB 前转换为对应数值类型,具体实现:

针对 CSV 解析:

解析时对每个字段尝试转换为数值类型:

import csv
from decimal import Decimal

def convert_to_numeric(value):
    try:
        return int(value)
    except ValueError:
        try:
            return Decimal(value)  # 用Decimal处理小数,避免浮点精度问题
        except ValueError:
            return value  # 无法转换则保留字符串

with open('data.csv', 'r') as f:
    reader = csv.DictReader(f)
    for row in reader:
        for key, val in row.items():
            row[key] = convert_to_numeric(val)
        db_collection.insert_one(row)

针对带引号数字的 JSON:

解析 JSON 后遍历数据转换字符串型数字:

import json
from decimal import Decimal

def convert_to_numeric(value):
    try:
        return int(value)
    except ValueError:
        try:
            return Decimal(value)
        except ValueError:
            return value

def parse_json_with_numeric(json_str):
    data = json.loads(json_str)
    for key, val in data.items():
        if isinstance(val, str):
            data[key] = convert_to_numeric(val)
    return data

# 示例使用
json_str = '{"key": "test", "myInteger": "21", "myCurrency": "25.97"}'
processed_data = parse_json_with_numeric(json_str)
db_collection.insert_one(processed_data)

附:你的测试代码及结果

测试代码

from decimal import * 
from pymongo import MongoClient
import datetime  # 补充原代码缺失的导入

my_int_a = "21"
my_int_b = 21

row_dict = {}
row_dict['key'] = 'my string (default)'
row_dict['myInteger'] = int(21)
row_dict['myInteger2'] = 21
row_dict['myInteger3'] = my_int_a
row_dict['myInteger4'] = my_int_b
# row_dict['myCurrencyDecimal'] = Decimal(25.97)
row_dict['myCurrencyDouble'] = 25.97
row_dict['myDateInsertedFmt'] = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.000Z")
row_dict['myDateInsertedNow'] = datetime.datetime.now()

db_collection_test_datatypes.insert_one(row_dict)
db_collection_test_datatypes.insert_one(row_dict)

json_dict = {
    'key': 'my json key',
    'myInteger': 21,
    'myCurrencyDouble': 25.97
}
db_collection_test_datatypes.insert_one(json_dict)

查询结果

{
    "_id": ObjectId("653052a351416c5223bbeee7"),
    "key": "my string (default)",
    "myInteger": NumberInt("21"),
    "myInteger2": NumberInt("21"),
    "myInteger3": "21",
    "myInteger4": NumberInt("21"),
    "myCurrencyDouble": 25.97,
    "myDateInsertedFmt": "2023-10-18T16:48:19.000Z",
    "myDateInsertedNow": ISODate("2023-10-18T16:48:19.411Z")
}
{
  "_id": ObjectId("65305109485c0394d26e8983"),
  "key": "my json key",
  "myInteger": NumberInt("21"),
  "myCurrencyDouble": 25.97
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:30:58