英文:
to find the last index of the array in mongodb
问题
在后端,我使用Go语言,数据库使用MongoDB。我正在尝试找到嵌套数组中最后插入的文档,以便我可以在不知道其索引的情况下检索最后一个数组索引中的文档。目前,我正在获取所有员工的文档,然后找到最后一个索引。这样做会导致我的RAM超载,因为我需要在找到数组的最后一个索引之前检索1000条员工记录并将其存储在RAM中。
我的结构如下:
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
}
)
以下是我在应用程序中的代码:
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
正如你所看到的,我检索了整个员工数据,然后找到了最后一个文档的ID。有没有更好的方法来做到这一点?感谢任何帮助。谢谢。
新添加的代码
这段代码是基于你的示例:
var result bson.M
query := bson.M{"empid": "1234"} // 获取你感兴趣的员工
match := bson.M{"$match": query} // 设置管道的匹配部分
unwind := bson.M{"$unwind": "$leave"} // 设置要展开的leave字段
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()
这段代码给我返回了很多相同的文档,例如542个文档,但所有这些文档都是相同的。
英文:
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...
答案1
得分: 1
如果你正在运行一个具有 $slice 功能的Mongo版本,它是在2.4版本中引入的,你可以在Find中使用它,并添加一个Select函数,它的工作方式类似于project。
err = c.Find(bson.M{"empid": "1234"}).Select(bson.M{"name": 1, "leave": bson.M{"$slice": -1}}).One(&result) // result是一个Employee结构体
否则,聚合是你的朋友。你需要使用一个管道并展开Employee的Leave字段。
以下是几个简单的步骤:
1)根据你的Employee记录定义一个结果记录,其中Leave字段被定义为单个LeaveInfo而不是LeaveInfos的切片,例如:
type EmployeeResult struct {
Name string `bson:"name"`
Leave LeaveInfo `bson:"leave"`
}
不要忘记将bson标签的名称与Employee结构体中LeaveInfo标签的名称相同。
2)然后创建一个包含几个阶段的管道:
query := bson.M{"empid": "1234"} // 获取你感兴趣的员工
match := bson.M{"$match": query} // 设置管道的匹配部分
unwind := bson.M{"$unwind": "$leave"} // 设置要展开的leave字段
pipeline := []bson.M{match, unwind} // 你传递给pipe的管道。我喜欢将pipe调用的各个部分分开,以提高清晰度和后续修改的便利性。
3)使用管道作为参数调用Pipe,然后迭代结果,这样你就可以一次获取一个LeaveInfo。
var result EmployeeResult
iter := postCollection.Pipe(pipeline).Iter()
for iter.Next(&result) {
fmt.Printf("%+v\n", result)
}
iter.Close()
4)在循环结束时,result将包含列表中的最后一个项目,如果没有读取到任何内容,则为空。
英文:
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:
-
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 stringbson:"name"
Leave LeaveInfobson:"leave"
}
Do not forget to make the bson tag the same name as the LeaveInfo tag in the Employee struct. -
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 -
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() -
At the end of the loop, result will have the last item in the list, or be blank if nothing was read.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论