skip to Main Content

Here is a code fragment that I used to test. I’m trying to determine what happens when you use dictionary vs JSON style, and when you use a variable.

    from decimal import * 
    from pymongo import MongoClient
    
    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)

This is what I see in the database:

{
    "_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")
}    and 
    {
      "_id": ObjectId("65305109485c0394d26e8983"),
      "key": "my json key",
      "myInteger": NumberInt("21"),
      "myCurrencyDouble": 25.97
    }

NOTE: There is no ISODate wrapper on the formatted date. Somewhere I saw that the above is the format to use for storing a date in MongoDB. So if I have a date, I need to load it to a date type. (I have changed this question several times since I first posted it, where it wasn’t an ISODATE).

When I try to use the decimal (which is commented out above), I get this error:

bson.errors.InvalidDocument: cannot encode object:
Decimal(‘25.969999999999998863131622783839702606201171875’), of type:
<class ‘decimal.Decimal’>

Do I have to store the floating point value?

And Part 2 of my question, if I use JSON with quotes, then numbers arestored as strings? JSON seems to lack standards, many JSONs I see have all values in quotes, even the numbers. How would I deal with that?

In my actual application, I’m parsing a CSV into strings, but then I noticed that even the numbers were being stored as string instead of numbers, which I is why I wrote the above test and asked this question.

2

Answers


  1. Chosen as BEST ANSWER

    This is still a code fragment, but shows how to use the Decimal128. NOTE: You must wrap it with str() function before passing to Decimal128.

    from bson.decimal128 import Decimal128
    
        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'] = Decimal128(str(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)
    

    Creates this in MongoDB:

    {
        "_id": ObjectId("65305679b5fb74135f65c921"),
        "key": "my string (default)",
        "myInteger": NumberInt("21"),
        "myInteger2": NumberInt("21"),
        "myInteger3": "21",
        "myInteger4": NumberInt("21"),
        "myCurrencyDecimal": NumberDecimal("25.97"),
        "myCurrencyDouble": 25.97,
        "myDateInsertedFmt": "2023-10-18T17:04:41.000Z",
        "myDateInsertedNow": ISODate("2023-10-18T17:04:41.798Z")
    }
    

  2. For your date store as a string note that strftime as its name shown return a string.

    The pymongo library include an automatic formating of datetime and store it straight into the right format in Mongo.

    The same applies to float(not decimal) and int no need to cast because the type is dynamically asign in Python.

    I’ll recomand to use float as much as you can, and if you really need to use Decimal then you’ll need to convert it to Decimal128.
    This topic has already been related see : Pymongo: Cannot encode object of type decimal.Decimal?

    Please let me know if you have some more questions i’ll be happy to help you with that

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search