найти последний индекс массива в mongodb

В серверной части я использую go lang, а для базы данных я использую mongoDB. Я пытаюсь найти последний документ, вставленный во встроенный массив, чтобы я мог получить документ в последнем индексе массива, не зная его индекса. Прямо сейчас я получаю все документы сотрудника, а затем нахожу последний индекс. Это похоже на перегрузку моя оперативная память, так как мне нужно получить 1000 записей о сотруднике и сохранить их в оперативной памяти, прежде чем найти последний индекс массива. Моя структура выглядит следующим образом

 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

        }

Вот как я делаю в своем приложении

 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

Как вы можете видеть, я извлекаю все данные о сотрудниках, а затем нахожу идентификатор последнего документа. Есть ли лучший способ сделать это. Благодарю за любую помощь. Пожалуйста... Спасибо..

Недавно добавленные коды

 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()

Этот код дает мне много таких же документов, как 542 документа. Но все эти документы одинаковы...


person Rajesh Kumar    schedule 11.11.2016    source источник


Ответы (1)


Если вы используете версию на Mongo, в которой есть $slice, она была представлена ​​в 2.4, вы можете использовать ее в поиске с добавлением функции выбора, которая работает как проект.

err = c.Find(bson.M{"empid": "1234"}).Select(bson.M{"name": 1, "leave": bson.M{"$slice": -1}}).One(&result) // result is an Employee struct

В противном случае агрегация — ваш друг. Вам нужно использовать конвейер и раскрутить поле «Отпуск сотрудника».

Есть несколько простых шагов:

1) Определите результирующую запись на основе вашей записи о сотруднике, где поле «Отпуск» определено как одиночное «LeaveInfo», а не как часть «LeaveInfos», например

EmployeeResult struct {
    Name   string    `bson:"name"`
    Leave  LeaveInfo `bson:"leave"`
}

Не забудьте присвоить тегу bson то же имя, что и тегу LeaveInfo в структуре Employee.

2) Затем создайте конвейер с парой этапов:

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) Вызовите Pipe с конвейером в качестве параметра, затем выполните Iter над результатами, это должно дать вам один LeaveInfo за раз

var (
    result EmployeeResult
)
iter := postCollection.Pipe(pipeline).Iter()
for iter.Next(&result) {
    fmt.Printf("%+v\n", result)
}
iter.Close()

4) В конце цикла результат будет иметь последний элемент в списке или будет пустым, если ничего не было прочитано.

person dgm    schedule 12.11.2016
comment
Спасибо, user1638680..... Есть ли какой-либо другой атрибут в mongodb, который помогает нам найти наименьший индекс. Это определенно лучше, чем мой код, но я не хочу, чтобы 1000 записей массива выходов извлекались внутри оперативной памяти для каждого request, хотя мы просто извлекаем только два атрибута массива leave. Спасибо... Еще раз спасибо за вашу помощь. - person Rajesh Kumar; 12.11.2016
comment
В Mongo 3.2 вы можете использовать $slice с отрицательным числом из оболочки Mongo, например - person dgm; 12.11.2016
comment
Упс, я преждевременно нажал кнопку возврата. В оболочке Mongo вы можете выполнить запрос, например: db.c.find({empid: 1234}, {leave: {$slice: -1 }}) и получить последнюю запись в массиве. Я бегло просмотрел и не нашел примеров использования $slice из Go. - person dgm; 12.11.2016
comment
Спасибо, что указали мне правильное направление. Я исследовал и нашел эту ссылку stackoverflow.com/questions/37253400/ я написал свой код на основе этого, но результат дает мне больше, чем отсутствие записей в массиве .Я обновлю свой вопрос, пожалуйста, взгляните на него и, пожалуйста, помогите решить эту проблему. Спасибо. - person Rajesh Kumar; 12.11.2016