to find the last index of the array in mongodb

huangapple go评论85阅读模式
英文:

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:

  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.

huangapple
  • 本文由 发表于 2016年11月11日 17:19:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/40544700.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定