AsifArmanRahman / firebase-rest-api

A simple python wrapper for Google's Firebase REST API's.
https://firebase-rest-api.readthedocs.io
MIT License
60 stars 14 forks source link

[Bug]: Issue loading `dict` from subcollection #7

Closed D3nii closed 1 year ago

D3nii commented 1 year ago

Is there an existing issue for this?

Environment

-   OS: MacOS 10.15.7
-   Python: 3.9

What happened?

I am saving a collection within a collection. Data being saved in the nested collection looks something like:

bonus_data = {
                "title": title,
                "start_date": start_date,
                "end_date": end_date,
                "target": target,
                "prorata_start": prorata_start,
                "bonus_available": bonus_amount,
                "sales_units": sales_units,
                "filters": {
                    "Supplier": producers,
                    "Salesperson": salespersons,
                    "PriceDescription": price_descriptions,
                },
                "average_per_bottles": average_per_bottles,
            }

And it saves successfully, here is a screenshot of uploaded data: Screen Shot 2023-02-06 at 10 54 42 AM

But when I try to load the data from the subcollection, I'm running into:

TypeError: ('Cannot convert to a Python Value', {'arrayValue': {}}, 'Invalid type', <class 'dict'>)

Code Snippet

I'm saving the data into the storage using:
fsdb.collection("users").document(session.get("localId")).collection('bonuses').document(title).set(bonus_data)

I'm loading like this:
fsdb.collection("users").document(session.get("localId")).document(bonus_doc_title).get()

Relevant log output

No response

Anything else?

No response

github-actions[bot] commented 1 year ago

Hello @D3nii , thank you for submitting an issue! A project committer will shortly review the issue.

AsifArmanRahman commented 1 year ago

Hello @D3nii.

I'm loading like this: fsdb.collection("users").document(session.get("localId")).document(bonus_doc_title).get()

This is what you should be using fetch data from database.

fsdb.collection("users").document(session.get("localId")).collection('bonuses').document(bonus_doc_title).get()
D3nii commented 1 year ago

Thank you @AsifArmanRahman, but I think there must have been a typo in my copy. I'm using the exact query to fetch the data.

Let me share a bit more context. Here is a sample of the entries: Screen Shot 2023-02-06 at 6 09 14 PM

The query I am using to fetch the test bonus' data is:

fsdb.collection("users").document("9UETu306vIZIexl7BuIjLC7Grv53").collection("bonuses").document("test").get()

But still receive the same error.

Moreover, running the following command does give me output of ['test', 'test2']:

fsdb.collection("users").document("9UETu306vIZIexl7BuIjLC7Grv53").collection("bonuses").list_of_documents()
Lxstr commented 1 year ago

Could it be issue with empty arrays if filters are expected to be arrays? Could confirm this by deleting filters and then trying to get.

Secondly could remove all null values?

Thirdly could just set as json? Something to the effect of:

# Store a dictionary as a JSON string
json_data = json.dumps(bonus_data)
fsdb.collection("users").document(session.get("localId")).collection('bonuses').document(title).set(json_data)

# Retrieve the JSON string and convert it back to a dictionary
json_data = fsdb.collection("users").document("9UETu306vIZIexl7BuIjLC7Grv53").collection("bonuses").document("test").get().to_dict()
bonus_data = json.loads(json_data)
AsifArmanRahman commented 1 year ago

This is a snippet I used to write and fetch the data from the firestore, in the architecture as per visible in the screenshot you provided.

import json
from pprint import pprint
from decouple import config
from firebase import initialize_app

app = initialize_app(json.load(open('config.json')))

user = app.auth().sign_in_with_email_and_password(config('email'), config('password'))

db = app.firestore()

data_to_db = {
    'average_per_bottles': None,
    'bonus_available': 4000,
    'end_date': '2023-02-04',
    'filters': {
        'PriceDescription': None, 
        'SalesPerson': {
            'Supplier': None
        }
    },
    'prorata_start': None,
    'sales_unit': 'ItemTotal',
    'start_date': '2023-01-30',
    'target': 4000,
    'title': 'test'
}

# writes data
db.collection('users').document(user['localId']).collection('bonuses').document('test').set(data_to_db)

# fetches data
data_from_db = db.collection('users').document(user['localId']).collection('bonuses').document('test').get()

pprint(data_from_db)


Below is the screenshot of the data which was written in the database and matches exactly with the ss you provided.

image


Lastly, a ss is provided with the output received from the database.

Screenshot_20230208_125758


So, @D3nii, unless you can provide me with a snippet of code which produces the error you receive, I can't find any bug to resolve.

AsifArmanRahman commented 1 year ago

Could it be issue with empty arrays if filters are expected to be arrays? Could confirm this by deleting filters and then trying to get.

In the screenshot he provided, I see no trace of array field. The snippet I provided uses only string, null and map type fields to create same replica of the data. @Lxstr

D3nii commented 1 year ago

Thank you for the suggestions @Lxstr. I did try the json string method earlier, and ran into other issues with that.

@AsifArmanRahman, even after swapping the null values with -1 for now, I am getting the same error: Screen Shot 2023-02-08 at 3 25 43 AM

Command used to get:

fsdb.collection("users").document('9UETu306vIZIexl7BuIjLC7Grv53').collection("bonuses").document('latest try 3').get()

Error:

TypeError: ('Cannot convert to a Python Value', {'arrayValue': {}}, 'Invalid type', <class 'dict'>)
D3nii commented 1 year ago

UPDATE

@AsifArmanRahman, I think I've found what is messed up.

The code crashes and fails to fetch data if we have an empty array in the data somewhere. Haven't tested for first order variables, but nested to second degree, when equal to an empty array, is causing the issue.

So, this causes the error:

data = {
"name": ...,
...,
...,
"filter": {
"salesperson" : [],
},
}

Where as, this doesn't:

data = {
"name": ...,
...,
...,
"filter": {
"salesperson" : None,
},
}
AsifArmanRahman commented 1 year ago

Thank you for finding the reason why the error occurred. @D3nii Please upgrade to the latest version of the library which will resolve this issue.