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 活动选择题。最多可以参加几个项目?
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能
  • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面
  • ¥50 NT4.0系统 STOP:0X0000007B
  • ¥15 想问一下stata17中这段代码哪里有问题呀