- PVSM.RU - https://www.pvsm.ru -

MongoDB Go Driver туториал

Хорошие новости! Официальный драйвер go для mongoDB [1] вышел в бета-версию. Немного поразмыслив я решил перевести статью [2] с официального сайта mongoDB вместо того, чтобы писать материал самостоятельно. Вот что будет в этом туториале:

  • Установка mongo-go-driver
  • Соединение с mongoDB с помощью mongo-go-driver
  • Использование BSON объектов
  • Использование CRUD методов
    image
    Исходный код этого руководства находится в [этом GitHub репозитории](https://github.com/tfogo/mongodb-go-tutorial). Для работы с этим руководством требуется установленная MongoDB версии не ниже 3.2 и Golang 1.10 или старше.

Установка mongo-go-driver

Драйвер состоит из нескольких пакетов.
Вы можете установить драйвер с помощью go get:

go get github.com/mongodb/mongo-go-driver

Вывод может содержать в себе следующее предупреждение:

package github.com/mongodb/mongo-go-driver: no Go files in (...)

Это ожидаемый результат.

прим. переводчика: лично я использую модули и там все прекрасно.

Если вы используете в качестве менеджера для управления зависимостсями dep, то вам придется установить основной пакет mongo, также пакет bson и mongo/options:

dep ensure --add github.com/mongodb/mongo-go-driver/mongo 
github.com/mongodb/mongo-go-driver/bson 
github.com/mongodb/mongo-go-driver/mongo/options

Создание основы

Создайте проект и добавьте в него файл main.go со следующим содержимым:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/mongodb/mongo-go-driver/bson"
    "github.com/mongodb/mongo-go-driver/mongo"
    "github.com/mongodb/mongo-go-driver/mongo/options"
)

// You will be using this Trainer type later in the program
type Trainer struct {
    Name string
    Age  int
    City string
}

func main() {
    // Rest of the code will go here
}

В этом коде мы импортируем mongo-go-driver, некоторые стандартные библиотеки и определяем тип Trainer.

Соединение с mongoDB с помощью mongo-go-driver

После того как мы импортировали mongo-go-driver, у нас появилась возможность создать соединение с mongoDB использую функцию mongo.Connect(). У нас есть возможность передать в эту функцию в качестве аргуменов context и стороку содержащую адрес подключения к mongodb. При желании мы также можем передать в качестве третьего аргумента объект options.ClientOptions для тонкой настройки параметров драйвера. В документации [3] подробно описаны доступные парпметры.

Давайте добавим следующий код в тело функции main:

client, err := mongo.Connect(context.TODO(), "mongodb://localhost:27017")

if err != nil {
    log.Fatal(err)
}

// Check the connection
err = client.Ping(context.TODO(), nil)

if err != nil {
    log.Fatal(err)
}

fmt.Println("Connected to MongoDB!")

После успешного соединения с mongoDB мы можем обратиться к коллекции trainers, которая находится в базе с именем test добавив следующий код в конец функции main:

collection := client.Database("test").Collection("trainers")

Рекомендуется держать соединение с mongoDB открытым, чтобы не приходилось открывать и закрывать соединение для каждого запроса. Однако, если приложение больше не требует подключения, оно может быть закрыто с помощю функции client.Disconnect() следующим образом:

err = client.Disconnect(context.TODO())

if err != nil {
    log.Fatal(err)
}
fmt.Println("Connection to MongoDB closed.")

Закомментируйте неиспользуемые пакеты bson и mongo/options.

Запустите наш код (go run main.go) чтобы проверить подключение к серверу mongoDB.

Использовение BSON объектов

JSON документы в mongoDB хранятся в двоичном формате, называемом BSON. В отличие от других баз данных в которых JSON данные хранятся в виде строк и чисел, кодировка BSON добавляет новые типы, такие как int, long, date, float и decimal128.

Это значительно упрощает обработку, сортировку и сравнение данных приложениями. Драйвер Go имеет два семейства типов для представления данных BSON: Типы D и типы RAW.

Семейство D состоит из четырех типов:

  • D: документ BSON. Этот тип следует использовать в ситуациях, когда порядок имеет значение, например, команды MongoDB.
  • M: Неупорядоченный словарь(ассоциативный массив, map). Он такой же, как D, за исключением того, что он не сохраняет порядок.
  • A: массив BSON.
  • E: одиночный элемент внутри D.

Вот пример фильтра, построенного с использованием D-типов, который производит поиск документов, в которых поле name соответствует значениям Alice или Bob:

Семейство типов Raw используется для проверки среза байтов. Вы можете извлечь одиночные элементы из типов Raw, используя Lookup() [4].

Это может быть полезно когда необходимо избавиться от лишней нагрузки при конвертировании BSON в иной тип. В этом туториале будет использоваться только семейство типов D.

Использование CRUD методов

После успешного соединения с базой данных, мы можем начать добавлять и изменять данные в нашей коллекции. Тип Collection содержит в себе методы позволяющие отправлять запросы в базу данных.

Вставка (создание) документов

Для начала необходимо создать несколько новых структур Trainer для вставки в базу данных:

ash := Trainer{"Ash", 10, "Pallet Town"}
misty := Trainer{"Misty", 10, "Cerulean City"}
brock := Trainer{"Brock", 15, "Pewter City"}

Для того чтобы всавить одиночный документ следует использовать метод collection.InsertOne():

insertResult, err := collection.InsertOne(context.TODO(), ash)
if err != nil {
    log.Fatal(err)
}

fmt.Println("Inserted a single document: ", insertResult.InsertedID)

Для вставки нескольких документов одновременно существут метод collection.InsertMany():

trainers := []interface{}{misty, brock}

insertManyResult, err := collection.InsertMany(context.TODO(), trainers)
if err != nil {
    log.Fatal(err)
}

fmt.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs)

Обновление документов

Метод collection.UpdateOne() позволяет обновить один документ. Требуется создать фильтр для поиска документа в базе данных и документ для операции обновления. Вы можете создать их, используя типы bson.D:

filter := bson.D{{"name", "Ash"}}

update := bson.D{
    {"$inc", bson.D{
        {"age", 1},
    }},
}

Следующий код найдет документ, в котором поле name совпадает со значением Ash и увеличит значение age на 1.

updateResult, err := collection.UpdateOne(context.TODO(), filter, update)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Matched %v documents and updated %v documents.n", updateResult.MatchedCount, updateResult.ModifiedCount)

Поиск документов

Чтобы найти документ, вам понадобится фильтр, а также указатель на переменную, в которую может быть декодирован результат.

Чтобы найти один документ, используйте collection.FindOne(). Этот метод возвращает одно значение, которое можно декодировать в переменную.

Мы будем использовать ту же переменную фильтра, которую использовали в запросе на обновление.

// create a value into which the result can be decoded
var result Trainer

err = collection.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Found a single document: %+vn", result)

Чтобы найти несколько документов, используйте collection.Find().

Этот метод возвращает Cursor. Cursor предоставляет поток документов, с помощью которого можно перебирать и декодировать по одному документу за раз.

Когда документы в Cursor исчерпываются, следует закрыть Cursor. Также Cursor можно тонко настроить использую пакет options.

В нашем примере, мы устанавливаем лимит на выдачу двух документов.

// Pass these options to the Find method
options := options.Find()
options.SetLimit(2)

// Here's an array in which you can store the decoded documents
var results []*Trainer

// Passing nil as the filter matches all documents in the collection
cur, err := collection.Find(context.TODO(), nil, options)
if err != nil {
    log.Fatal(err)
}

// Finding multiple documents returns a cursor
// Iterating through the cursor allows us to decode documents one at a time
for cur.Next(context.TODO()) {

    // create a value into which the single document can be decoded
    var elem Trainer
    err := cur.Decode(&elem)
    if err != nil {
        log.Fatal(err)
    }

    results = append(results, &elem)
}

if err := cur.Err(); err != nil {
    log.Fatal(err)
}

// Close the cursor once finished
cur.Close(context.TODO())

fmt.Printf("Found multiple documents (array of pointers): %+vn", results)

Удаление документов

Вы можете удалить документы, используя collection.DeleteOne() или collection.DeleteMany().
Мы передаем nil в качестве аргумента фильтра, который будет соответствовать всем документам в коллекции. Также можно использовать collection.Drop() для удаления всей коллекции.

deleteResult, err := collection.DeleteMany(context.TODO(), nil)
if err := cur.Err(); err != nil {
    log.Fatal(err)
}
fmt.Printf("Deleted %v documents in the trainers collectionn", deleteResult.DeletedCount)

Далнейшие шаги

→ Финальный код этого туториала находится в репозитории GitHub [5]
→ Документация к драйверу достпна в GoDoc [6]

Если у вас есть какие-либо вопросы, пожалуйста, свяжитесь с нами в группе Google mongo-go-driver [7].
Пожалуйста, отправляйте отчеты об ошибках в MongoDB JIRA [8].
Мы будем рады получить ваши отзывы о Go Driver.

Автор: pocoZ

Источник [9]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/perevod/302852

Ссылки в тексте:

[1] драйвер go для mongoDB: https://github.com/mongodb/mongo-go-driver/

[2] статью: https://www.mongodb.com/blog/post/mongodb-go-driver-tutorial

[3] В документации: https://godoc.org/github.com/mongodb/mongo-go-driver/mongo/options

[4] Lookup(): https://godoc.org/github.com/mongodb/mongo-go-driver/bson#Raw.Lookup

[5] репозитории GitHub: https://github.com/tfogo/mongodb-go-tutorial

[6] достпна в GoDoc: https://godoc.org/github.com/mongodb/mongo-go-driver

[7] Google mongo-go-driver: https://groups.google.com/forum/#!forum/mongodb-go-driver

[8] MongoDB JIRA: https://www.google.com/url?q=https%3A%2F%2Fjira.mongodb.org%2Fprojects%2FGODRIVER&sa=D&sntz=1&usg=AFQjCNEOEt6d3ZNOMKzmT23RYOVYdjSD6g

[9] Источник: https://habr.com/post/433776/?utm_campaign=433776