Reputation: 207
In the back end i m using go lang and for database i use mongoDB. I m trying to find the last document inserted in the embedded array so i can retrieve the document in the last array index without knowing its index.Right now i m getting all the documents of the employee and then find the last index.It is like overloading my RAM as i need to retrieve 1000 of record of employee and store it in ram before finding the last index of the array My struct is as follows
type (
Employee struct {
Name string
Password string
EmpId string
EmailAddress string
Position string
Gender string
Nationality string
Department string
MaritalStatus string
Approvedby string
JoinDate time.Time
ConfirmationDate time.Time
EndDate time.Time
Leave []*LeaveInfo
}
LeaveInfo struct {
Total float64
Id int
Days float64
From time.Time
To time.Time
Status string
Certificate []*CertificateInfo
}
CertificateInfo struct {
FileName string
FileType string
FileSize int
}
Here is how i do in my application
My code is follows
employee := Employee{}
err = c.Find(bson.M{
"empid": "1234"
}).One(&result)
if err != nil {
log.Fatal(err)
}
name:=result.Name
lastindex:= result.LeaveInfo[len(result.LeaveInfo)-1].Id
As you can see i retrive the whole employee data and then find the Id of the last document.Is there any better way to do this.Appreciate any help.Please ...Thanks..
Newly Added Codes
This code is based on your example
var result bson.M
query := bson.M{"empid": "1234"} // gets the employee you are interested in
match := bson.M{"$match": query} // Set up the match part of the pipeline
unwind := bson.M{"$unwind": "$leave"} // sets up the leave field to be unwound
pipeline := []bson.M{match, unwind,{
"$project":bson.M{
"ID":bson.M{
"$slice": []interface{}{"$leave.id", -1},
}
}
iter := postCollection.Pipe(pipeline).Iter()
for iter.Next(&result) {
fmt.Printf("%+v\n", result)
}
iter.Close()
This code gives me lot of same document like 542 documents .But all these document are same...
Upvotes: 1
Views: 680
Reputation: 123
If you are running a version on Mongo which has $slice in it, It was introduced in 2.4, you can use it in a Find with the addition of a Select Function, which works like project.
err = c.Find(bson.M{"empid": "1234"}).Select(bson.M{"name": 1, "leave": bson.M{"$slice": -1}}).One(&result) // result is an Employee struct
Otherwise, aggregation is your friend. You need to use a pipeline and unwind the Employee Leave field.
There are a few simple steps:
1) Define a result record based on your Employee record where the Leave field is defined as a single LeaveInfo rather than a slice of LeaveInfos, eg
EmployeeResult struct {
Name string `bson:"name"`
Leave LeaveInfo `bson:"leave"`
}
Do not forget to make the bson tag the same name as the LeaveInfo tag in the Employee struct.
2) Then create a pipeline with a couple of stages:
query := bson.M{"empid": "1234"} // gets the employee you are interested in
match := bson.M{"$match": query} // Set up the match part of the pipeline
unwind := bson.M{"$unwind": "$leave"} // sets up the leave field to be unwound
pipeline := []bson.M{match, unwind} // the pipeline you are passing to pipe. I like to split the parts of the pipe call up for clarity and ease of later modification
3) Call Pipe with the pipeline as a parameter then Iter over the results, this should give you one LeaveInfo at a time
var (
result EmployeeResult
)
iter := postCollection.Pipe(pipeline).Iter()
for iter.Next(&result) {
fmt.Printf("%+v\n", result)
}
iter.Close()
4) At the end of the loop, result will have the last item in the list, or be blank if nothing was read.
Upvotes: 1