duanfu7994 2016-11-11 09:19
浏览 264

在mongodb中查找数组的最后一个索引

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
", result)
    }
    iter.Close()

This code gives me lot of same document like 542 documents .But all these document are same...

  • 写回答

1条回答 默认 最新

  • dousi2553 2016-11-12 00:52
    关注

    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
    ", 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.

    评论

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题