1

I'll try to be as clear as possible. I'm building a simple audit logging API, using MongoDB, and Model-Vew-Controller architecture. As part of the functionality, the user can request data using a http endpoint. When the endpoint is hit, the controller package calls the model package, and the code below is executed:

// The GetResourceData function takes the resource, and provides the log data for that resource, sorted by // date and time. It also takes a context.context, and a *mongo.Client as parameters. func GetResourceData(ctx context.Context, CL *mongo.Client, Resource string) error { ourDatabase := CL.Database("Event_Database") eventsCollection := ourDatabase.Collection("Events") opts := options.Find() opts.SetSort(bson.D{{"Date", -1}, {"Time", -1}}) filterCursor, err := eventsCollection.Find( ctx, bson.M{"Resource": Resource}, opts) if err != nil { log.Fatal(err) } defer filterCursor.Close(ctx) for filterCursor.Next(ctx) { var eventsFiltered []bson.D if err = filterCursor.All(ctx, &eventsFiltered); err != nil { log.Fatal(err) } fmt.Println(eventsFiltered) } return err } 

This works fine, and as you can see, I've printed the eventsFiltered to the terminal. It doesn't do much good there however, and I need to print it to the screen. I have a function that's ready to do this in the view package with a http.ResponseWriter, BUT - I cannot figure out how to convert the bson.D to a string format so I can cleanly pass this in as a parameter. If I try bson.Unmarshall;

 var cookie []byte bson.Unmarshal(cookie, eventsFiltered) s := string(cookie) fmt.Println("Events filtered as a string is: ", s) fmt.Println("Events filtered as a byte slice is: ", cookie) 

I get the following;

Users filtered as a string is:

Users filtered as a byte slice is: []

...an empty string, or an empty byte slice. I know there is something really simple I'm missing, but I can't see it!

Any help would be greatly appreciated. Please ask if you have any questions.

Thanks, A

1 Answer 1

2

First of all, if you use filterCursor.All(ctx, &eventsFiltered), you don't need to either iterate trough all the collection or close the cursor (cursor method All(...) will do it for you).


What about your question, you can do for example something like this:

 var eventsFiltered []bson.D if err = filterCursor.All(ctx, &eventsFiltered); err != nil { log.Fatal(err) } for _, event := range eventsFiltered { for _, keyValPair := range event { fmt.Printf("key is %s; val is %v", keyValPair.Key, keyValPair.Value) } } 

Or, in case an order of elements doesn't matter, consider unmarshalling into bson.M:

 var eventsFiltered []bson.M if err = filterCursor.All(ctx, &eventsFiltered); err != nil { log.Fatal(err) } for _, event := range eventsFiltered { for key, val := range event { fmt.Printf("key is %s; val is %v", key, val) } } 

So, the whole solution would be:

func GetResourceData(ctx context.Context, CL *mongo.Client, Resource string) error { ourDatabase := CL.Database("Event_Database") eventsCollection := ourDatabase.Collection("Events") opts := options.Find() opts.SetSort(bson.D{{"Date", -1}, {"Time", -1}}) filterCursor, err := eventsCollection.Find( ctx, bson.M{"Resource": Resource}, opts) if err != nil { log.Fatal(err) } if filterCursor.Next(ctx) { var eventsFiltered []bson.M if err = filterCursor.All(ctx, &eventsFiltered); err != nil { log.Fatal(err) } // If you need ordered print, uncomment the following lines and comment out following uncommented for loop // for _, event := range eventsFiltered { // for _, keyValPair := range event{ // fmt.Printf("key is %s; val is %v", keyValPair.Key, keyValPair.Value) // } // } for _, event := range eventsFiltered { for key, val := range event { fmt.Printf("key is %s; val is %v", key, val) } } } return nil } 
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, it looks so simple, but it's an elegant solution. I have just two questions: 1) When attempting to use the code block for the ordered print, the Key and Value properties of KeyValuePair used for the %s and %v verbs are showing as unresolved references. keyValPair is showing as an interface, so perhaps this is a factor? 2) This solution successfully prints (and allows for formatting, which I didn't have before), however I'm looking to save that printed string as a string in a variable, which I can then pass around and do with as I need. I'll see if I can work it out
I can't edit my above comment, BUT - point 2 has now been taken care of, which just leaves the unresolved references from your ordered results solution.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.