需要在mgo中使用分页

I am using Go as the back end and MongoDB as the database and use beego framework to develop this application. I would like to do some pagination in my front end.

My struct looks like this:

type Employee struct {
        Name               string
        EmpId              string
        Password           string
        PhoneNumber        int32
        EmailAddress       string
        Position           string
        AccessLevel        string
        Gender             string
        MaritalStatus      string
        Nationality        string
        Department         string
        ICNumber           string
        JoinDate           time.Time
        ConfirmationDate   time.Time
        EndDate            time.Time
        AnnualLeave        []*AnnualLeaveInfo
        MedicalLeave       []*MedicalLeaveInfo
        NopayLeave         []*NopayLeaveInfo
        ChildcareLeave     []*ChildcareLeaveInfo
    }

type AnnualLeaveInfo struct {
        Id           int
        Days         float64
        Type         string
        From         time.Time
        To           time.Time
        AppliedDate  time.Time
        Status       string
        Certificate  []*CertificateInfo
    }

The other leave info as same as the annual leave info. I would like to show all the leaves of all the employee documents sorted by applied date and status. Right now I'm retrieving all the leave details and then appending in array and then I am using the cursor value (last retrieved index value of the array which I pass to the front end in the previous response) and finding the values from the array. I know that this is not a good function because for every request it needs to retrieve all the leave details for retrieving only 20 leave details which is requested by the front end.

My Results after appending in the array is like this

  "0": {
    "LeaveEmpId": "rajeshk",
    "Name": "rahul",
    "LeaveId": 8,
    "LeaveType": "annualleave",
    "LeaveTotal": 2,
    "LeaveDays": 1,
    "LeaveFrom": "2016-12-12T08:00:00+08:00",
    "LeaveTo": "2016-12-12T08:00:00+08:00",
    "LeaveAppliedDate": "2016-11-21T10:29:33.713+08:00",
    "LeaveStatus": "Processing",
    "CertificateName": [
      "1.pdf",
      "2.pdf"
    ]
  },
  "1": {
    "LeaveEmpId": "rajeshk",
    "LeaveName": "Rajesh",
    "LeaveId": 7,
    "LeaveType": "medicalleave",
    "LeaveTotal": 3,
    "LeaveDays": 1,
    "LeaveFrom": "2016-12-12T08:00:00+08:00",
    "LeaveTo": "2016-12-12T08:00:00+08:00",
    "LeaveAppliedDate": "2016-11-21T10:27:06.12+08:00",
    "LeaveStatus": "Processing",
    "CertificateName": [
      "1.pdf",
      "2.pdf"
    ]
  },
  "2": {
    "LeaveEmpId": "kumar",
    "LeaveName": "madia",
    "LeaveId": 6,
    "LeaveType": "nopayleave",
    "LeaveTotal": 4,
    "LeaveDays": 1,
    "LeaveFrom": "2016-12-12T08:00:00+08:00",
    "LeaveTo": "2016-12-12T08:00:00+08:00",
    "LeaveAppliedDate": "2016-11-21T10:11:58.283+08:00",
    "LeaveStatus": "Processing",
    "CertificateName": [
      "1.pdf",
      "2.pdf"
    ]
  },
  "3": {
    "LeaveEmpId": "master",
    "LeaveName": "kumar",
    "LeaveId": 5,
    "LeaveType": "nopayleave",
    "LeaveTotal": 5,
    "LeaveDays": 1,
    "LeaveFrom": "2016-12-12T08:00:00+08:00",
    "LeaveTo": "2016-12-12T08:00:00+08:00",
    "LeaveAppliedDate": "2016-11-21T10:02:17.565+08:00",
    "LeaveStatus": "Processing",
    "CertificateName": [
      "1.pdf",
      "2.pdf"
    ]
  },
  "4": {
    "LeaveEmpId": "rajeshk",
    "LeaveName": "Rajesh",
    "LeaveId": 4,
    "LeaveType": "medicalleave",
    "LeaveTotal": 6,
    "LeaveDays": 1,
    "LeaveFrom": "2016-12-12T08:00:00+08:00",
    "LeaveTo": "2016-12-12T08:00:00+08:00",
    "LeaveAppliedDate": "2016-11-21T09:52:20.185+08:00",
    "LeaveStatus": "Processing",
    "CertificateName": [
      "1.pdf",
      "2.pdf"
    ]
  },
  "5": {
    "LeaveEmpId": "rajeshk",
    "LeaveName": "Rajesh",
    "LeaveId": 3,
    "LeaveType": "annualleave",
    "LeaveTotal": 7,
    "LeaveDays": 1,
    "LeaveFrom": "2016-12-12T08:00:00+08:00",
    "LeaveTo": "2016-12-12T08:00:00+08:00",
    "LeaveAppliedDate": "2016-11-21T09:49:18.702+08:00",
    "LeaveStatus": "Processing",
    "CertificateName": [
      "1.pdf",
      "2.pdf"
    ]
  },
  "6": {
    "LeaveEmpId": "india",
    "LeaveName": "rahul",
    "LeaveId": 2,
    "LeaveType": "nopayleave",
    "LeaveTotal": 8,
    "LeaveDays": 1,
    "LeaveFrom": "2016-12-12T08:00:00+08:00",
    "LeaveTo": "2016-12-12T08:00:00+08:00",
    "LeaveAppliedDate": "2016-11-21T09:30:14.99+08:00",
    "LeaveStatus": "Processing",
    "CertificateName": [
      "1.pdf",
      "2.pdf"
    ]
  },
  "7": {
    "LeaveEmpId": "rajeshk",
    "LeaveName": "Rajesh",
    "LeaveId": 1,
    "LeaveType": "medicalleave",
    "LeaveTotal": 9,
    "LeaveDays": 1,
    "LeaveFrom": "2016-12-12T08:00:00+08:00",
    "LeaveTo": "2016-12-12T08:00:00+08:00",
    "LeaveAppliedDate": "2016-11-21T09:28:02.785+08:00",
    "LeaveStatus": "Processing",
    "CertificateName": [
      "1.pdf",
      "2.pdf"
    ]
 }

In the database my empid is only index I use which is unique other values are not unique. Leave id is unique only with in the leave array. Can someone help me how to do this efficiently. Appreciate any help. Thanks.

Added Info:

My Database Structure looks like this ...This is just the info of one employee. Like this I have lots of employee documents. What I need is to get the total leave details of all these employee documents with the limit of 20 for pagination sorted by applieddate and status. Thanks

{
    "_id" : ObjectId("58320cec720fed31a3243683"),
    "name" : "Rajesh",
    "empid" : "rajeshk",
    "password" : "c1e1a43a3d65ff4d669f2831b9908acb9e2f755c48280e99f0d7a3e92592fa29",
    "phonenumber" : 0,
    "emailaddress" : "example@example.com.sg",
    "position" : "string",
    "accesslevel" : "string",
    "gender" : "string",
    "maritalstatus" : "string",
    "nationality" : "india",
    "department" : "it",
    "icnumber" : "string",
    "childcitizenship" : "string",
    "joindate" : ISODate("2015-11-21T00:00:00.000Z"),
    "confirmationdate" : Date(-62135596800000),
    "enddate" : Date(-62135596800000),
    "totalchild" : 0,
    "annualleave" : [ 
        {

            "id" : 0,
            "days" : 0.0,
            "type" : "",
            "from" : Date(-62135596800000),
            "to" : Date(-62135596800000),
            "applieddate" : Date(-62135596800000),
            "status" : "",
            "approveddate" : Date(-62135596800000),
            "certificate" : []
        }
    ],
    "medicalleave" : [ 
        {

            "id" : 0,
            "days" : 0.0,
            "type" : "",
            "from" : Date(-62135596800000),
            "to" : Date(-62135596800000),
            "applieddate" : Date(-62135596800000),
            "status" : "",
            "approveddate" : Date(-62135596800000),
            "certificate" : []
        }
    ],
    "nopayleave" : [ 
        {
            "total" : 10.0,
            "id" : 0,
            "days" : 0.0,
            "type" : "",
            "from" : Date(-62135596800000),
            "to" : Date(-62135596800000),
            "applieddate" : Date(-62135596800000),
            "status" : "",
            "approveddate" : Date(-62135596800000),
            "certificate" : []
        }, 
        {
            "total" : 9.0,
            "id" : 1,
            "days" : 1.0,
            "mdays" : 0.0,
            "type" : "nopayleave",
            "daytype" : "FullDay",
            "from" : ISODate("2016-12-12T00:00:00.000Z"),
            "to" : ISODate("2016-12-12T00:00:00.000Z"),
            "applieddate" : ISODate("2016-11-21T01:28:02.785Z"),
            "status" : "Processing",
            "approveddate" : Date(-62135596800000),
            "certificatename" : "",
            "certificate" : [ 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }, 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }
            ]
        }, 
        {
            "total" : 8.0,
            "id" : 2,
            "days" : 1.0,
            "mdays" : 0.0,
            "type" : "nopayleave",
            "daytype" : "FullDay",
            "from" : ISODate("2016-12-12T00:00:00.000Z"),
            "to" : ISODate("2016-12-12T00:00:00.000Z"),
            "applieddate" : ISODate("2016-11-21T01:30:14.990Z"),
            "status" : "Processing",
            "approveddate" : Date(-62135596800000),
            "certificatename" : "",
            "certificate" : [ 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }, 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }
            ]
        }, 
        {
            "total" : 7.0,
            "id" : 3,
            "days" : 1.0,
            "mdays" : 0.0,
            "type" : "nopayleave",
            "daytype" : "FullDay",
            "from" : ISODate("2016-12-12T00:00:00.000Z"),
            "to" : ISODate("2016-12-12T00:00:00.000Z"),
            "applieddate" : ISODate("2016-11-21T01:49:18.702Z"),
            "status" : "Processing",
            "approveddate" : Date(-62135596800000),
            "certificatename" : "",
            "certificate" : [ 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }, 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }
            ]
        }, 
        {
            "total" : 6.0,
            "id" : 4,
            "days" : 1.0,
            "mdays" : 0.0,
            "type" : "nopayleave",
            "daytype" : "FullDay",
            "from" : ISODate("2016-12-12T00:00:00.000Z"),
            "to" : ISODate("2016-12-12T00:00:00.000Z"),
            "applieddate" : ISODate("2016-11-21T01:52:20.185Z"),
            "status" : "Processing",
            "approveddate" : Date(-62135596800000),
            "certificatename" : "",
            "certificate" : [ 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }, 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }
            ]
        }, 
        {
            "total" : 5.0,
            "id" : 5,
            "days" : 1.0,
            "mdays" : 0.0,
            "type" : "nopayleave",
            "daytype" : "FullDay",
            "from" : ISODate("2016-12-12T00:00:00.000Z"),
            "to" : ISODate("2016-12-12T00:00:00.000Z"),
            "applieddate" : ISODate("2016-11-21T02:02:17.565Z"),
            "status" : "Processing",
            "approveddate" : Date(-62135596800000),
            "certificatename" : "",
            "certificate" : [ 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }, 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }
            ]
        }, 
        {
            "total" : 4.0,
            "id" : 6,
            "days" : 1.0,
            "mdays" : 0.0,
            "type" : "nopayleave",
            "daytype" : "FullDay",
            "from" : ISODate("2016-12-12T00:00:00.000Z"),
            "to" : ISODate("2016-12-12T00:00:00.000Z"),
            "applieddate" : ISODate("2016-11-21T02:11:58.283Z"),
            "status" : "Processing",
            "approveddate" : Date(-62135596800000),
            "certificatename" : "",
            "certificate" : [ 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }, 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }
            ]
        }, 
        {
            "total" : 3.0,
            "id" : 7,
            "days" : 1.0,
            "mdays" : 0.0,
            "type" : "nopayleave",
            "daytype" : "FullDay",
            "from" : ISODate("2016-12-12T00:00:00.000Z"),
            "to" : ISODate("2016-12-12T00:00:00.000Z"),
            "applieddate" : ISODate("2016-11-21T02:27:06.120Z"),
            "status" : "Processing",
            "approveddate" : Date(-62135596800000),
            "certificatename" : "",
            "certificate" : [ 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }, 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }
            ]
        }, 
        {
            "total" : 2.0,
            "id" : 8,
            "days" : 1.0,
            "mdays" : 0.0,
            "type" : "nopayleave",
            "daytype" : "FullDay",
            "from" : ISODate("2016-12-12T00:00:00.000Z"),
            "to" : ISODate("2016-12-12T00:00:00.000Z"),
            "applieddate" : ISODate("2016-11-21T02:29:33.713Z"),
            "status" : "Processing",
            "approveddate" : Date(-62135596800000),
            "certificatename" : "",
            "certificate" : [ 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }, 
                {
                    "filename" : "Rajesh",
                    "filetype" : ".zip",
                    "filesize" : 1234
                }
            ]
        }
    ],
    "childcareleave" : [ 
        {
            "total" : 10.0,
            "id" : 0,
            "days" : 0.0,
            "type" : "",
            "from" : Date(-62135596800000),
            "to" : Date(-62135596800000),
            "applieddate" : Date(-62135596800000),
            "status" : "",
            "approveddate" : Date(-62135596800000),
            "certificate" : []
        }
    ],
    "hospitalleave" : [ 
        {
            "total" : 10.0,
            "id" : 0,
            "days" : 0.0,
            "mdays" : 0.0,
            "type" : "",
            "daytype" : "",
            "from" : Date(-62135596800000),
            "to" : Date(-62135596800000),
            "applieddate" : Date(-62135596800000),
            "status" : "",
            "approveddate" : Date(-62135596800000),
            "certificatename" : "string",
            "certificate" : []
        }
    ],
    "maternityleave" : [ 
        {
            "total" : 10.0,
            "id" : 0,
            "days" : 0.0,
            "mdays" : 0.0,
            "type" : "",
            "daytype" : "",
            "from" : Date(-62135596800000),
            "to" : Date(-62135596800000),
            "applieddate" : Date(-62135596800000),
            "status" : "",
            "approveddate" : Date(-62135596800000),
            "certificate" : []
        }
    ],
    "paternityleave" : [ 
        {
            "total" : 0.0,
            "id" : 0,
            "days" : 0.0,
            "mdays" : 0.0,
            "type" : "",
            "daytype" : "",
            "from" : Date(-62135596800000),
            "to" : Date(-62135596800000),
            "applieddate" : Date(-62135596800000),
            "status" : "",
            "approveddate" : Date(-62135596800000),
            "certificate" : []
        }
    ],
    "compassionateleave" : [ 
        {
            "total" : 0.0,
            "id" : 0,
            "days" : 0.0,
            "type" : "",
            "from" : Date(-62135596800000),
            "to" : Date(-62135596800000),
            "applieddate" : Date(-62135596800000),
            "status" : "",
            "approveddate" : Date(-62135596800000),
            "certificate" : []
        }
    ],
    "marriageleave" : [ 
        {
            "total" : 0.0,
            "id" : 0,
            "days" : 0.0,
            "type" : "",
            "from" : Date(-62135596800000),
            "to" : Date(-62135596800000),
            "applieddate" : Date(-62135596800000),
            "status" : "",
            "approveddate" : Date(-62135596800000),
            "certificate" : []
        }
    ],
    "otherleave" : []
}

Being as it is, you can't really achieve a much more efficient pagination, since all the documents you want to list and paginate are in a single document, separated into multiple slices/arrays.

To achieve efficient and simple pagination, I would refactor your model. First I would store all kinds of XXLeave documents as the same type, Leave, and add a property to it which tells you what kind of leave it is (e.g. Annual, Medical etc.). Next, I would not store this list in the Employee itself, but rather in a separate MongoDB collection, and it could have an EmployeeID field, telling to which employee a Leave document belongs to (owner).

Having this model, you can easily list a specific type of Leave documents of an employee with a query like:

c := session.DB("").C("leaves")
err := c.Find(bson.M{"empid": eid, "type": LeaveAnnual}).All(&result)

To list all Leave documents of an employee, simply don't use the "type" filter:

err := c.Find(bson.M{"empid": eid}).All(&result)

Now on to pagination. If you have this model, pagination becomes a piece of cake:

q = c.Find(bson.M{"empid": eid}).Sort("applieddate", "status")
// Use Skip() and Limit() to denote the page you want to send, e.g.
q = Skip((page-1) * 20).Limit(20)
err := q.All(&result)

If you want to send and paginate over all Leave documents regardless of the Employee (the author), then also leave out the EmpId filter:

err := c.Find(nil).Sort("applieddate", "status").
    Skip((page-1) * 20).Limit(20).All(&result)

Note that using Skip() and Limit() works great for "small" number of documents. But for large number of documents you should use pagination based on specifying starting index entry. See this question for more details and a ready-to-use library for it:

Efficient paging in MongoDB using mgo