I Want to fetch all records in database By using NAME but, if I am using ALL it is showing 500 internal error but, if I Kept One(JSON) I am getting only one record. What is the solution to fetch all records by Name?
func (uc UserController) Filter(c *gin.Context) {
var name = c.Params.ByName("Name")
var json models.User
err := c.Bind(&json)
if err != nil {
log.Fatal("error")
return
}
json.Name = name
fi := bson.D{{"Name", name}}
err = uc.session.DB(DB_NAME).C(DB_COLLECTION).Find(fi).All(json)
if err == nil {
c.Writer.Header().Set("Content-Type", "application/json")
c.JSON(201, &json)
} else {
c.JSON(500, gin.H{"result": "An error occured"})
}
}
You should pass an array (var json []models.User) to the All(&json) function, but you're passing one item (var json models.User).
Related
I'm trying to search a document in golang using mongodb driver. But the result is always blank.
This is my code:
var bsonString bson.M
var jsonString string
fmt.Printf("[%s] > request for url\n", req.RemoteAddr)
w.Header().Set("Access-Control-Allow-Origin", "*")
dataSource := client.Database(dbName)
collection := dataSource.Collection(collectionName)
err := collection.FindOne(context.Background(), bson.D{{"question.title", "Question"}}).Decode(&bsonString)
if err != nil {
if err == mongo.ErrNoDocuments {
// This error means your query did not match any documents.
log.Println("No matched documents!")
return
}
panic(err)
}
finalBytes, _ := bson.Marshal(bsonString)
bson.Unmarshal(finalBytes, &jsonString)
fmt.Println(jsonString)
My data is:
{"_id":{"$oid":"631c5c78e606582e2ad78e2d"},"question":{"title":"Question","create_by":"AZ","time":{"$numberLong":"1661394765044"},"detail":"<h4>info</h4>"},"answers":[{"create_by":"baa","time":{"$numberLong":"1661394765044"},"detail":"<h4>abc</h4>"}]}
You are unmarshalling a document into a string. If you did error handling you would see the error:
// no error haldling
json.Unmarshal(finalBytes, &jsonString)
// with error handling
err = json.Unmarshal(finalBytes, &jsonString)
if err != nil {
fmt.Println(err)
// prints: json: cannot unmarshal object into Go value of type string
}
You can create a struct to match your data or unmarshal into interface (for unstructured data).
// declare variables
var bsonString bson.M
var jsonString string
dataSource := client.Database(dbName)
collection := dataSource.Collection(collectionName)
//
dataObject := map[string]interface{}{}
fmt.Printf("[%s] > request for url\n", req.RemoteAddr)
// set headers
w.Header().Set("Access-Control-Allow-Origin", "*")
err := collection.FindOne(context.Background(), bson.D{{"question.title", "Question"}}).Decode(&bsonString)
if err != nil {
if err == mongo.ErrNoDocuments {
// This error means your query did not match any documents.
log.Println("No matched documents!")
return
}
panic(err)
}
// marshal & unmarshall
finalBytes, _ := bson.Marshal(bsonString)
bson.Unmarshal(finalBytes, &dataObject)
fmt.Println(dataObject)
I can't append struct object to array object in golang (GIN Framework)
func (dish *DishesController) RetrieveMultipleDishesItemsByCategoryId(c *gin.Context) {
//TODO 1 :Bind Json from request body
// 2: Call function for read document in mongodb by categoryId
// 3. Response data, finish
var categoryFromRequest DishesModel.CategoryFromRequest
if err := c.ShouldBindJSON(&categoryFromRequest); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"message": err.Error()})
return
}
for _, items := range categoryFromRequest.Category{
// loop call function for get dishes info
data, err := newService.FindDishesByID(items.Id)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"message": err.Error()})
return
}
categoryFromRequest.Category = append(categoryFromRequest.Category, data)
}
enter image description here
enter image description here
Slice/Array in Go must have all its elements be the same data type. Since categoryFromRequest.Category (type of []struct{...}) and data (type of DishesModel.DishesDataModel) are not the same types, you cannot append it to an array.
I'm retrieving the data from the database when the user hit the url like http://localhost:8080/api/v1/customer?keyword=dhiman then it search for the data in the collection if there is any field matches then it will retrieve that data. if the user entered the short url like http://localhost:8080/api/v1/customer?keyword=dhi then it also retrieve the data which matches like that how I'll solve this problem. I tried the code for this like following:-
Struct of the customer
type Customer struct {
Id int `json:"id" bson:"_id"`
FirstName string `json:"first_name" bson:"first_name"`
LastName string `json:"last_name" bson:"last_name"`
Email string `json:"email" bson:"email"`
PhoneNumber string `json:"phone_number" bson:"phone_number"`
}
type Customers []Customer
Functions
func GetCustomers(c *gin.Context) {
value := c.Query("keyword")
fmt.Println(value)
response := ResponseControllerList{}
conditions := bson.M{"last_name":value}
data, err := models.GetCustomerListing(conditions)
if err != nil {
response = ResponseControllerList{
config.FailureCode,
config.FailureFlag,
config.FailureMsg,
nil,
nil,
}
} else {
response = ResponseControllerList{
config.SuccessFlag,
config.SuccessFlag,
config.SuccessMsg,
data,
// dataCount,
nil,
}
}
GetResponseList(c, response)
}
GetCustomerListing function in models page:-
func GetCustomerListing(customerQuery interface{}) (result Customers, err error) {
mongoSession := config.ConnectDb()
sessionCopy := mongoSession.Copy()
defer sessionCopy.Close()
getCollection := mongoSession.DB(config.Database).C(config.CustomerCollection)
err = getCollection.Find(customerQuery).Select(bson.M{"password": 0}).All(&result) //.Skip(skip).Limit(limit)
if err != nil {
return result, err
}
return result, nil
}
collection images
I got the answer it is done by using the $or in mongodb.
In the monogdb there is a operator called or $or it checks the value with all the fields and produce result.
There is a bson.RegExis used. Because it will matches or checks the data similar to it receives from the user.
There is change in condition. The condition is:-
conditions := bson.M{"$or": []bson.M{
bson.M{"first_name": bson.RegEx{value,""}},
bson.M{"last_name": bson.RegEx{value,""}},
bson.M{"email": bson.RegEx{value,""}},
bson.M{"phone_number": bson.RegEx{value,""}},
}}
there is change in the query
Now I'm doing:
sess := mongodb.DB("mybase").C("mycollection")
var users []struct {
Username string `bson:"username"`
}
err = sess.Find(nil).Select(bson.M{"username": 1, "_id": 0}).All(&users)
if err != nil {
fmt.Println(err)
}
var myUsers []string
for _, user := range users{
myUsers = append(myUsers, user.Username)
}
Is there a more effective way to get slice with usernames from Find (or another search function) directly, without struct and range loop?
The result of a MongoDB find() is always a list of documents. So if you want a list of values, you have to convert it manually just as you did.
Using a custom type (derived from string)
Also note that if you would create your own type (derived from string), you could override its unmarshaling logic, and "extract" just the username from the document.
This is how it could look like:
type Username string
func (u *Username) SetBSON(raw bson.Raw) (err error) {
doc := bson.M{}
if err = raw.Unmarshal(&doc); err != nil {
return
}
*u = Username(doc["username"].(string))
return
}
And then querying the usernames into a slice:
c := mongodb.DB("mybase").C("mycollection") // Obtain collection
var uns []Username
err = c.Find(nil).Select(bson.M{"username": 1, "_id": 0}).All(&uns)
if err != nil {
fmt.Println(err)
}
fmt.Println(uns)
Note that []Username is not the same as []string, so this may or may not be sufficient to you. Should you need a user name as a value of string instead of Username when processing the result, you can simply convert a Username to string.
Using Query.Iter()
Another way to avoid the slice copying would be to call Query.Iter(), iterate over the results and extract and store the username manually, similarly how the above custom unmarshaling logic does.
This is how it could look like:
var uns []string
it := c.Find(nil).Select(bson.M{"username": 1, "_id": 0}).Iter()
defer it.Close()
for doc := (bson.M{}); it.Next(&doc); {
uns = append(uns, doc["username"].(string))
}
if err := it.Err(); err != nil {
fmt.Println(err)
}
fmt.Println(uns)
I don't see what could be more effective than a simple range loop with appends. Without all the Mongo stuff your code basically is this and that's exactly how I would do this.
package main
import (
"fmt"
)
type User struct {
Username string
}
func main() {
var users []User
users = append(users, User{"John"}, User{"Jane"}, User{"Jim"}, User{"Jean"})
fmt.Println(users)
// Interesting part starts here.
var myUsers []string
for _, user := range users {
myUsers = append(myUsers, user.Username)
}
// Interesting part ends here.
fmt.Println(myUsers)
}
https://play.golang.com/p/qCwENmemn-R
In MongoDB doing something like db.mycollection.find() returns all documents in a collection.
When working in GoLang using the package labix.org/v2/mgo and I do for example:
query := db.C("client").Find();
It complains that it requires input in the form of an interface. All I need to do is retrieve all documents and iterate through them and display each one for now. How do I achieve this effect? All examples I have seen seem to have filters in place.
Found a solution:
var results []client
err := db.C("client").Find(nil).All(&results)
if err != nil {
// TODO: Do something about the error
} else {
fmt.Println("Results All: ", results)
}
func (uc UserController) GetUsersList(w http.ResponseWriter,r *http.Request,p httprouter.Params){
var u []models.User
// Fetch user
if err := uc.session.DB("mydb").C("users").Find(nil).All(&u); err != nil {
w.WriteHeader(404)
fmt.Println("Results All: ", u)
return
}
uj, _ := json.Marshal(u)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
fmt.Fprintf(w, "%s", uj)
}