banner
biuaxia

biuaxia

"万物皆有裂痕,那是光进来的地方。"
github
bilibili
tg_channel

【Reprint】Go Language Operations on MongoDB

title: 【转载】Go Language Operations on mongoDB
date: 2021-08-09 16:38:33
comment: false
toc: true
category:

  • Golang
    tags:
  • Reprint
  • Go
  • MongoDB
  • Mongo
  • Operations

This article is reprinted from: Go Language Operations on mongoDB | Li Wenzhou's Blog


mongoDB is currently a popular database based on distributed file storage. It is a product that lies between relational databases and non-relational databases (NoSQL), and it is the most feature-rich and relational-like among non-relational databases.

Introduction to mongoDB#

mongoDB is currently a popular database based on distributed file storage. It is a product that lies between relational databases and non-relational databases (NoSQL), and it is the most feature-rich and relational-like among non-relational databases.

In mongoDB, a piece of data is stored as a document, and the data structure consists of key-value pairs. The document is similar to the JSON objects we commonly use in programming. The field values in the document can contain other documents, arrays, and arrays of documents.

The related concepts in mongoDB compared to the SQL concepts we are familiar with are as follows:

MongoDB Terms/ConceptsDescriptionComparison SQL Terms/Concepts
databaseDatabasedatabase
collectionCollectiontable
documentDocumentrow
fieldFieldcolumn
indexIndexIndex
primary keyPrimary key MongoDB automatically sets the _id field as the primary keyprimary key

mongoDB Installation#

Here we download and install the community version, official download link. After opening the above link, select the corresponding version, operating system platform (common platforms are supported), and package type, then click the Download button to download.

It is worth noting that there are two package types for the Windows platform: * ZIP: Compressed file version * MSI: Executable file version, click "Next" to install.

For macOS, in addition to downloading the TGZ file from this webpage, you can also install it using Homebrew.

For more installation details, you can refer to the official installation tutorial, which includes installation tutorials for the three major platforms: Linux, macOS, and Windows.

Basic Usage of mongoDB#

Starting mongoDB Database#

Windows#

"C:\Program Files\MongoDB\Server\4.2\bin\mongod.exe" --dbpath="c:\data\db"  

Mac#

mongod --config /usr/local/etc/mongod.conf  

or

brew services start [email protected]  

Starting Client#

Windows#

"C:\Program Files\MongoDB\Server\4.2\bin\mongo.exe"  

Mac#

mongo  

Common Database Commands#

show dbs;: View databases

> show dbs;  
admin   0.000GB  
config  0.000GB  
local   0.000GB  
test    0.000GB  

use q1mi;: Switch to the specified database, if it does not exist, it will be created.

> use q1mi;  
switched to db q1mi  

db;: Display the current database.

> db;  
q1mi  

db.dropDatabase(): Delete the current database

> db.dropDatabase();  
{ "ok" : 1 }  

Common Dataset Commands#

db.createCollection(name,options): Create a dataset

  • name: Dataset name
  • options: Optional parameters, specify memory size and index.
> db.createCollection("student");  
{ "ok" : 1 }  

show collections;: View all collections in the current database.

> show collections;  
student  

db.student.drop(): Delete the specified dataset

> db.student.drop()  
true  

Common Document Commands#

Insert a document:

> db.student.insertOne({name:"Little Prince",age:18});  
{  
	"acknowledged" : true,  
	"insertedId" : ObjectId("5db149e904b33457f8c02509")  
}  

Insert multiple documents:

> db.student.insertMany([  
... {name:"Zhang San",age:20},  
... {name:"Li Si",age:25}  
... ]);  
{  
	"acknowledged" : true,  
	"insertedIds" : [  
		ObjectId("5db14c4704b33457f8c0250a"),  
		ObjectId("5db14c4704b33457f8c0250b")  
	]  
}  

Query all documents:

> db.student.find();  
{ "_id" : ObjectId("5db149e904b33457f8c02509"), "name" : "Little Prince", "age" : 18 }  
{ "_id" : ObjectId("5db14c4704b33457f8c0250a"), "name" : "Zhang San", "age" : 20 }  
{ "_id" : ObjectId("5db14c4704b33457f8c0250b"), "name" : "Li Si", "age" : 25 }  

Query documents where age > 20:

> db.student.find(  
... {age:{$gt:20}}  
... )  
{ "_id" : ObjectId("5db14c4704b33457f8c0250b"), "name" : "Li Si", "age" : 25 }  

Update document:

> db.student.update(  
... {name:"Little Prince"},  
... {name:"Old Prince",age:98}  
... );  
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  
> db.student.find()  
{ "_id" : ObjectId("5db149e904b33457f8c02509"), "name" : "Old Prince", "age" : 98 }  
{ "_id" : ObjectId("5db14c4704b33457f8c0250a"), "name" : "Zhang San", "age" : 20 }  
{ "_id" : ObjectId("5db14c4704b33457f8c0250b"), "name" : "Li Si", "age" : 25 }  

Delete document:

> db.student.deleteOne({name:"Li Si"});  
{ "acknowledged" : true, "deletedCount" : 1 }  
> db.student.find()  
{ "_id" : ObjectId("5db149e904b33457f8c02509"), "name" : "Old Prince", "age" : 98 }  
{ "_id" : ObjectId("5db14c4704b33457f8c0250a"), "name" : "Zhang San", "age" : 20 }  

There are too many commands, for more commands please refer to the official documentation: shell commands and official documentation: CRUD operations.

Go Language Operations on mongoDB#

We are using the official driver package here, but you can also use third-party driver packages (such as mgo, etc.). The official Go driver for mongoDB was released relatively late (December 13, 2018).

Install mongoDB Go Driver Package#

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

Connect to mongoDB via Go Code#

package main  

import (  
	"context"  
	"fmt"  
	"log"  

	"go.mongodb.org/mongo-driver/mongo"  
	"go.mongodb.org/mongo-driver/mongo/options"  
)  

func main() {  
	// Set client connection options  
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")  

	// Connect to MongoDB  
	client, err := mongo.Connect(context.TODO(), clientOptions)  
	if err != nil {  
		log.Fatal(err)  
	}  

	// Check connection  
	err = client.Ping(context.TODO(), nil)  
	if err != nil {  
		log.Fatal(err)  
	}  
	fmt.Println("Connected to MongoDB!")  
}  

After connecting to MongoDB, you can handle the student dataset in our q1mi database with the following statement:

// Specify the dataset to operate on  
collection := client.Database("q1mi").Collection("student")  

After completing the task, you can disconnect from MongoDB with the following command:

// Disconnect  
err = client.Disconnect(context.TODO())  
if err != nil {  
	log.Fatal(err)  
}  
fmt.Println("Connection to MongoDB closed.")  

Connection Pool Mode#

import (  
	"context"  
	"time"  

	"go.mongodb.org/mongo-driver/mongo"  
	"go.mongodb.org/mongo-driver/mongo/options"  
)  

func ConnectToDB(uri, name string, timeout time.Duration, num uint64) (*mongo.Database, error) {  
	ctx, cancel := context.WithTimeout(context.Background(), timeout)  
	defer cancel()  
	o := options.Client().ApplyURI(uri)  
	o.SetMaxPoolSize(num)  
	client, err := mongo.Connect(ctx, o)  
	if err != nil {  
		return nil, err  
	}  

	return client.Database(name), nil  
}  

BSON#

JSON documents in MongoDB are stored in a binary representation called BSON (Binary JSON). Unlike other databases that store JSON data as simple strings and numbers, BSON encoding extends the JSON representation to include additional types such as int, long, date, float, and decimal128. This makes it easier for applications to reliably handle, sort, and compare data.

The Go driver for connecting to MongoDB has two main types to represent BSON data: D and Raw.

The D family of types is used to succinctly construct BSON objects using native Go types. This is particularly useful for constructing commands passed to MongoDB. The D family includes four types:

  • D: A BSON document. This type should be used when order is important, such as in MongoDB commands.
  • M: An unordered map. It is the same as D, but it does not maintain order.
  • A: A BSON array.
  • E: An element inside D.

To use BSON, you need to import the following package:

import "go.mongodb.org/mongo-driver/bson"  

Here is an example of a filter document constructed using the D type, which can be used to find documents where the name field matches 'Zhang San' or 'Li Si':

bson.D{{  
	"name",  
	bson.D{{  
		"$in",  
		bson.A{"Zhang San", "Li Si"},  
	}},  
}}  

The Raw family of types is used for validating byte slices. You can also use Lookup() to retrieve a single element from the raw type. This is very useful if you want to avoid the overhead of deserializing BSON into another type. In this tutorial, we will only use the D type.

CRUD#

We now define a Student type in our Go code as follows:

type Student struct {  
	Name string  
	Age  int  
}  

Next, create some values of the Student type to prepare for insertion into the database:

s1 := Student{"Little Red", 12}  
s2 := Student{"Little Blue", 10}  
s3 := Student{"Little Yellow", 11}  

Insert Document#

Use the collection.InsertOne() method to insert a document record:

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

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

Use the collection.InsertMany() method to insert multiple document records:

students := []interface{}{s2, s3}  
insertManyResult, err := collection.InsertMany(context.TODO(), students)  
if err != nil {  
	log.Fatal(err)  
}  
fmt.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs)  

Update Document#

The updateone() method allows you to update a single document. It requires a filter document to match the document in the database and an update document to describe the update operation. You can use the bson.D type to construct the filter and update documents:

filter := bson.D{{"name", "Little Blue"}}  

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

Next, you can find Little Blue and increase his age by one with the following statement:

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)  

Find Document#

To find a document, you need a filter document and a pointer to a value that can decode the result. To find a single document, use collection.FindOne(). This method returns a result that can be decoded into a value.

We use the filter defined above to find the document with the name 'Little Blue':

// Create a Student variable to receive the query result  
var result Student  
err = collection.FindOne(context.TODO(), filter).Decode(&result)  
if err != nil {  
	log.Fatal(err)  
}  
fmt.Printf("Found a single document: %+v\n", result)  

To find multiple documents, use collection.Find(). This method returns a cursor. The cursor provides a stream of documents that you can iterate over and decode one document at a time. When the cursor is exhausted, it should be closed. The following example uses the options package to set a limit to return only two documents.

// Query multiple  
// Pass options to Find()  
findOptions := options.Find()  
findOptions.SetLimit(2)  

// Define a slice to store query results  
var results []*Student  

// Use bson.D{{}} as a filter to match all documents  
cur, err := collection.Find(context.TODO(), bson.D{{}}, findOptions)  
if err != nil {  
	log.Fatal(err)  
}  

// Find multiple documents returns a cursor  
// Iterating over the cursor allows us to decode one document at a time  
for cur.Next(context.TODO()) {  
	// Create a value to decode a single document into  
	var elem Student  
	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 when done  
cur.Close(context.TODO())  
fmt.Printf("Found multiple documents (array of pointers): %#v\n", results)  

Delete Document#

Finally, you can use collection.DeleteOne() or collection.DeleteMany() to delete documents. If you pass bson.D{{}} as the filter parameter, it will match all documents in the dataset. You can also use collection.drop() to delete the entire dataset.

// Delete the one named Little Yellow  
deleteResult1, err := collection.DeleteOne(context.TODO(), bson.D{{"name", "Little Yellow"}})  
if err != nil {  
	log.Fatal(err)  
}  
fmt.Printf("Deleted %v documents in the trainers collection\n", deleteResult1.DeletedCount)  
// Delete all  
deleteResult2, err := collection.DeleteMany(context.TODO(), bson.D{{}})  
if err != nil {  
	log.Fatal(err)  
}  
fmt.Printf("Deleted %v documents in the trainers collection\n", deleteResult2.DeletedCount)  

For more methods, please refer to the official documentation.

https://docs.mongodb.com/manual/mongo/

https://www.mongodb.com/blog/post/mongodb-go-driver-tutorial

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.