mongodbgofibers

Go-MongoDriver decoding JSON array weirdly


Heyho party people,

I've recently took up learning Go and started working on a small side project which includes a API written using the Go Fiber library. All the necessery data is stored in MongoDB with the following schema

{
    "ObjectId": {
        "name": "name",
        "url": "url",
        "dateAdded": "date",
        "data": [{
                "timestamp 1": "price 1"
            },
            {
                "timestamp 2": "price 2"
            }
        ]
    }
}

The item type looks like this:

type Item struct {
    ID        primitive.ObjectID `json:"_id" bson:"_id"`
    Name      string             `json:"name" bson:"name"`
    URL       string             `json:"url" bson:"url"`
    DateAdded string             `json:"dateAdded" bson:"dateAdded"`
    Data      []interface{}      `json:"data" bson:"data"`
}

Whenever I query a stored item with

err = collection.FindOne(context.TODO(), filter).Decode(&item)

each map inside of the data-array is wrapped in another array =>

{ test url 2021-04-16 [[{2021-04-16 99.99}] [{2021-04-17 109.99}]] }

instead of

{ test url 2021-04-16 [{2021-04-16 99.99}, {2021-04-17 109.99}] }

Does anybody have an idea on how to fix this? Thanks in advance!


Solution

  • OK, I've found a way to fix this behaviour for my use case.

    As mentioned above, the MongoDB-driver for Go wraps each entry of an array into another respective array, which leads to a nested array.

    After trying around for some time I found out, that inserting the document into your collection like the following example,

    db.collection.insertOne({ name: "Name", url: "URL", dateAdded: "2021-04-25", data: { "2021-04-25": 9.99, "2021-04-26": 19.99 } })
    

    then the result of a query performed in your program looks like this:

    { ObjectID("60858245f8805dc57a716500") Name URL 2021-04-25 [{ 2021-04-25 9.99 } { 2021-04-26 19.99 }] }
    

    This means, that the JSON-schema should look like this

    {
        "ObjectId": {
            "name": "name",
            "url": "url",
            "dateAdded": "date",
            "data": {
                "2021-04-25": 9.99,
                "2021-04-26": 19.99
            }
        }
    }
    

    Sadly, I was not able to find out what is actually causing this odd behaviour, but I hope this helps anybody encountering this (or a similar) problem.

    EDIT

    Changing the type of the Data-field to []bson.M, as mkopriva said in the comments below, fixed it.

    type Item struct {
        ID        primitive.ObjectID `json:"_id" bson:"_id"`
        Name      string             `json:"name" bson:"name"`
        URL       string             `json:"url" bson:"url"`
        DateAdded string             `json:"dateAdded" bson:"dateAdded"`
        Data      []bson.M           `json:"data" bson:"data"`
    }
    

    This way the original JSON-schema does not have to be adapted to the workaround.

    {
        "ObjectId":{
            "name":"name",
            "url":"url",
            "dateAdded":"date",
            "data": [
                {
                    "2021-04-25": 9.99
                },
                {
                    "2021-04-26": 19.99
                }
            ]
        }
    }