-3

I am getting the following error while deleting from key from array of JSON objects using Go. Error:

    repository/orderRepository.go:394:11: first argument to delete must be map; have interface {}
    repository/orderRepository.go:395:11: first argument to delete must be map; have interface {}
    repository/orderRepository.go:396:11: first argument to delete must be map; have interface {}
    repository/orderRepository.go:397:11: first argument to delete must be map; have interface {}
    repository/orderRepository.go:398:11: first argument to delete must be map; have interface {}

I am explaining my code below.

    func SyncOrders() map[string]interface{} {
        logger.Log.Println("OrderRepository SyncOrders Begin")
        resourceManager := resources.ResourceManager{}
        session, error := driver.Connect()
        db := session.DB(config.Configuration.Database)
        var resp map[string]interface{}

        if error != nil {
            resp := utils.Message(resourceManager.GetProperty(constants.ERROR), resourceManager.GetProperty(constants.DB_SERVER_NOT_REACHABLE_CODE), resourceManager.GetProperty(constants.DB_SERVER_NOT_REACHABLE_DESC))
            return resp
        } else {
            var result []interface{}
            //filter := bson.M{"Customer.CustomerID": id, "PaymentDetails.PaymentStatus": "Payment Received"}
            //fmt.Println(filter)
            err := db.C(ORDERCOLLECTION).Find(nil).All(&result)
            if err == nil {
                resp = utils.Message(resourceManager.GetProperty(constants.SUCCESS), resourceManager.GetProperty(constants.PRODUCT_GETBYID_CODE), resourceManager.GetProperty(constants.PRODUCT_GETBYID_DESC))
                for i := 1; i < len(result); i++ {

                    delete(result[i],"_id");
                    delete(result[i],"CreatedAt");
                    delete(result[i],"CreatedBy");
                    delete(result[i],"UpdatedAt");
                    delete(result[i],"UpdatedBy");
                }
                resp["data"] = result
            } else {
                //fmt.Println(err)
                resp = utils.Message(resourceManager.GetProperty(constants.ERROR), resourceManager.GetProperty(constants.PRODUCT_GETBYID_NOTFOUND_CODE), resourceManager.GetProperty(constants.PRODUCT_GETBYID_NOTFOUND_DESC))
            }
            defer session.Close()
            return resp
        }
    }

Here I am fetching some record from MongoDB and delete some key value from each record but when I am running the server I am getting these errors. As I am beginner to Go. Can anybody help me to resolve these errors?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
user_agent
  • 65
  • 9

2 Answers2

3

The error message says it all: the first argument to the builtin delete() must be a value of static type map.

Your result variable is of type []interface{}, so indexing it like result[i] will result in a value of type interface{}.

If it holds a map, you may use type assertion to obtain the map value from it. Since you use the mgo driver, it is of type bson.M (which is a map[string]interface{}), so you may do it like this:

delete(result[i].(bson.M), "_id")

But it would be better if you would declare result to be a slice of maps in the first place:

var result []bson.M

So then no type assertion will be needed, and the following will be valid code:

delete(result[i], "_id")

Also note that if you want to remove these properties from the results, it would be best if you would tell MongoDB you don't need these fields and so the server wouldn't even send these (saving network traffic) and then you wouldn't have to remove them (saving time and memory).

Use projection to tell you don't need these fields. In mgo you can set a projection using the Query.Select() method.

For example:

err := db.C(ORDERCOLLECTION).Find(nil).Select(bson.M{
    "_id":       0,
    "CreatedAt": 0,
    "CreatedBy": 0,
    "UpdatedAt": 0,
    "UpdatedBy": 0,
}).All(&result)

The above query will result in documents where the listed fields will not be present, so you don't have to manually remove them using delete().

icza
  • 389,944
  • 63
  • 907
  • 827
  • Yes i used like `delete(result[i].(bson.M), "_id")` and error gone. – user_agent Apr 09 '20 at 09:29
  • @user_agent But rather declare `result` to be `[]bson.M`, so you don't have to use type assertion. – icza Apr 09 '20 at 09:29
  • Is there any other way rather than for loop where I can delete same keys from each record of document as loops takes too many time. – user_agent Apr 09 '20 at 09:48
  • @user_agent Yes, use a projection to tell the server you don't need these fields, so you won't have to remove them at all. See edited answer how to do that. – icza Apr 09 '20 at 10:29
0

You are trying to delete key from variable of type interface{}. @icza gives a good solution.

You can use .Select() to select which fields should be retrieved for the results. Then you don't need to delete those fields from every object.

For example, the following query would only retrieve the name and age field:

err := db.C(ORDERCOLLECTION).Find(nil).Select(bson.M{"name": 1, "age": 1}).All(&result)
Eklavya
  • 17,618
  • 4
  • 28
  • 57