13 декабря 2018 года MongoDB выпустила свой официальный драйвер Go в бета-версию, готовую к тестированию более широким сообществом Go и MongoDB. улучшая функциональность и возможности изо дня в день. Это руководство основано на официальном руководстве, выпущенном MongoDB, но я постарался сделать его как можно более простым вместе с рабочим справочником.

TL; DR: исходный код можно найти здесь с операциями CRUD.

В этом уроке мы рассмотрим:

  • Установите драйвер MongoDB Go
  • Подключите MongoDB с помощью драйвера Go
  • Использование объектов BSON в Go
  • Выполнение операций CRUD
  1. Установка драйвера MongoDB Go

Драйвер MongoDB Go состоит из нескольких пакетов. Если вы просто используете go get, вы можете установить драйвер, используя:

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

Результат может выглядеть как предупреждение, указывающее что-то вроде package github.com/mongodb/mongo-go-driver: no Go files in (...). Это ожидаемый результат.

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

govendor fetch github.com/mongodb/mongo-go-driver/mongo
govendor fetch go.mongodb.org/mongo-driver/bson
govendor fetch go.mongodb.org/mongo-driver/mongo/options

Все необходимые пакеты должны быть установлены, теперь давайте создадим соединение с Mongo.

2. Настройка подключения

После импорта драйвера MongoDB Go мы можем подключиться к развертыванию MongoDB с помощью Client.Connect(context). Нам нужно настроить нового клиента, нам нужно передать URI нашей базы данных mongo при настройке клиента. Затем нам просто нужно вызвать client.Connect(context) с контекстом, который установит наше соединение.

Следующий код устанавливает для нас соединение:

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

//Set up a context required by mongo.Connect
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
//To close the connection at the end
defer cancel()
//We need to set up a client first
//It takes the URI of your database
client, error := mongo.NewClient(options.Client().ApplyURI("your_database_uri"))
if error != nil {
    log.Fatal(err)
}
//Call the connect function of client
error = client.Connect(ctx)
//Checking the connection
error = client.Ping(context.TODO(), nil)
fmt.Println("Database connected")

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

Документы JSON в MongoDB хранятся в двоичном представлении, называемом BSON (JSON с двоичной кодировкой). В отличие от других баз данных, которые хранят данные JSON в виде простых строк и чисел, кодировка BSON расширяет представление JSON за счет включения дополнительных типов, таких как int, long, date, с плавающей запятой и decimal128. Это значительно упрощает приложениям надежную обработку, сортировку и сравнение данных. Драйвер Go имеет два семейства типов для представления данных BSON: типы D и типы Raw.

Семейство типов D используется для лаконичного построения объектов BSON с использованием собственных типов Go. Это может быть особенно полезно для создания команд, передаваемых в MongoDB. Семейство D состоит из четырех типов:

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

Вот пример документа с фильтром, построенного с использованием D типов, которые можно использовать для поиска документов, в которых поле name соответствует либо Алисе, либо Бобу:

bson.D{{
    "name", 
    bson.D{{
        "$in", 
        bson.A{"Alice", "Bob"}
    }}
}}

4. CRUD-операции

Для CRUD и других операций нам нужно использовать объект коллекции, который мы можем создать, обратившись к нашей соответствующей коллекции в нашей базе данных, например:

BooksCollection := client.Database("test").Collection("books")
  • Вставить

Для создания мы можем использовать collection.InsertOne () для отдельной записи или использовать collection.InsertMany (), который принимает фрагмент объектов.

/**
* Create - Adding a new book
* res -> the insert command returns the inserted id of the oject
*/
res, err := BooksCollection.InsertOne(ctx, bson.M{"name": "The Go Language", "genre": "Coding", "authorId": "4"})
if err != nil {
log.Fatal(err)
}

В collection.InsertOne () мы можем либо передать строковый объект через bson.M {}, либо создать объект нашей структуры соответствующего типа и передать этот объект.

  • Прочитать

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

filter := bson.D{{"name", "Book 1"}}
// create a value into which the result can be decoded
var result bookType

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

fmt.Printf("Found a single Book: %+v\n", result)

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

cur, error := BooksCollection.Find(ctx, bson.D{{}})
var allbooks []*bookType
//Loops over the cursor stream and appends to result array
for cur.Next(context.TODO()) {
var booksResultHolder bookType 
err := cur.Decode(&bookResultHolder)
if err != nil {
log.Fatal(err)
}
allbooks = append(allbooks, &booksResultHolder)
}
//dont forget to close the cursor
defer cur.Close(context.TODO())
// Loop over the result array and perform whatever required
for _, element := range allbooks {
book := *element
fmt.Println(book)
}

- Если вы получаете пустые результаты, проверьте свои поля структур типов, вы должны экспортировать поля структур, иначе они игнорируются пакетом mongodb-go-driver. (Каждое поле должно начинаться с заглавной буквы, указывая, что оно может быть экспортировано)

type users struct {
User string `bson:"user" json:"user"`
Data string `bson:"data" json:"data"`
}

По умолчанию, когда значение структуры преобразуется / сохраняется / извлекается из MongoDB, используется имя поля. Если вы хотите использовать разные имена, вы можете использовать теги, чтобы указать, каким именам должны соответствовать поля.

- Если ваши документы автоматически генерируют идентификаторы, в настоящий момент вы не сможете получить эти идентификаторы через mongodb-go-server, потому что идентификаторы представляют собой строки, заключенные в пользовательские объекты, и на данный момент драйвер их не поддерживает. Более подробную информацию можно найти здесь.

  • Обновить

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

/**
* Update
* Collection has functions like UpdateOne and UpdateMany
* Returns the Matched and Modified Count
*/
filter := bson.D{{"name", "Book 1"}}
// Need to specify the mongodb output operator too
newName := bson.D{
{"$set", bson.D{
{"name", "Updated Name of Book 1"},
}},
}
res, err := BooksCollection.UpdateOne(ctx, filter, newName)
if err != nil {
log.Fatal(err)
}
updatedObject := *res
fmt.Printf("The matched count is : %d, the modified count is : %d", updatedObject.MatchedCount, updatedObject.ModifiedCount)
  • Удалить

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

filter = bson.D{{"name", "Updated Name of Book 2"}}
deleteResult, error := BooksCollection.DeleteOne(ctx, filter)

Следующие шаги

Исходный код этого руководства можно найти здесь.

Документация для драйвера MongoDB Go доступна на GoDoc. Вас может особенно заинтересовать документация об использовании агрегатов или транзакций.

Надеюсь, этот урок упростил вам задачу, желаю всем удачи!