0

Insert Interface data with integer and double fields via Golang to MongoDB but integer fields was stored as double

I have to consume unstructure data from queue (JSON format) and bulk the data to MongoDB but the integer fields was store as double

Example Code

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    mongoURI := fmt.Sprintf("mongodb://%s:%s@%s:%d", "root", "root", "localhost", 27017)
    ctxtimeout, cancelCtx := context.WithTimeout(context.Background(), 60*time.Second)
    mongoConnection, err := mongo.NewClient(options.Client().ApplyURI(mongoURI))
    if err != nil {
        log.Fatal(err.Error())
    }
    defer cancelCtx()
    err = mongoConnection.Connect(ctxtimeout)
    if err != nil {
        log.Fatal(err.Error())
    }
    defer mongoConnection.Disconnect(ctxtimeout)
    mongoDatabase := mongoConnection.Database("dbname")
    mongoCollection := mongoDatabase.Collection("posts")

    str := `{ "number1": 10, "number2": 20.1 }`
    var data map[string]interface{}
    json.Unmarshal([]byte(str), &data)
    reMar, _ := json.Marshal(data)
    fmt.Println(string(reMar))
    mongoCollection.InsertOne(ctxtimeout, data)
}

The str variable is store the example data that I got from queue

This is the output that store to MongoDB. The number1 fields should stored as Int but it stored as Double

So, How to stored it as Int not double ?

output when store to mongo

  • related: https://stackoverflow.com/questions/8218484/mongodb-inserts-float-when-trying-to-insert-integer – Andy Oct 15 '21 at 10:09
  • @Andy Yes, Thank for your comment but the worker that I designed It never know the data type it just consume and bulk the data to collection. – Sippkron Raksakiart Oct 15 '21 at 10:21
  • Go, when unmarshaling a JSON Number into an `interface{}`, will by default use the `float64` type, regardless of the Number's value. See https://play.golang.org/p/2qhLIWF7u_j. If you want to store integers in Mongo, using JSON Numbers as the source data, do not use `interface{}` for unmarshaling that JSON. – mkopriva Oct 15 '21 at 10:26

1 Answers1

1

I just found solution by using json.NewDecoder with UseNumber()

Example code

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "strings"
    "time"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    mongoURI := fmt.Sprintf("mongodb://%s:%s@%s:%d", "root", "root", "localhost", 27017)
    ctxtimeout, cancelCtx := context.WithTimeout(context.Background(), 60*time.Second)
    mongoConnection, err := mongo.NewClient(options.Client().ApplyURI(mongoURI))
    if err != nil {
        log.Fatal(err.Error())
    }
    defer cancelCtx()
    err = mongoConnection.Connect(ctxtimeout)
    if err != nil {
        log.Fatal(err.Error())
    }
    defer mongoConnection.Disconnect(ctxtimeout)
    mongoDatabase := mongoConnection.Database("influencerdirectory")
    mongoCollection := mongoDatabase.Collection("posts")

    str := `{ "number1": 10, "number2": 20.1 }`
    var data map[string]interface{}
    d := json.NewDecoder(strings.NewReader(str))
    d.UseNumber()
    d.Decode(&data)
    // json.Unmarshal([]byte(str), &data)
    reMar, _ := json.Marshal(data)
    fmt.Println(string(reMar))
    mongoCollection.InsertOne(ctxtimeout, data)
}

Result:

enter image description here

Ref : Need to parse integers in JSON as integers, not floats