gomongo

package module
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 21, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

README

gomongo

Gomongo is a very thin wrapper to mongo go driver. If increase productivity and code reliablity by using generics to represent a document. Also this wrapper respond with a single structure that holds all the inforamtion you need.

Each mongo function can be executed as sync or go function. In case you are using go function, this module returns a none blocking channel. You can drain the channel whenever you like to get the result of the operation. This is good for starting several actions and then collect the result down the code.

Installing

use the following command to add gomongo to your project


go get gitlab.com/sagiforbes/gomongo


Usage examples

create client struct

You start by creating a client struct to be used by all gomongo functions. In this example we run mongo as a single node on localhost. To get a client run

import "gitlabcom/sagi.forbes/gomongo"

func main(){
  mongo_host="mongodb://127.0.0.1"
  var gmc = gomongo.NewClient(mongo_host, "my_database", 60*time.Second)
}

gmc can be used with all gomongo functions. my_database is the name of the database you want to use. 60*time.Seconds the timeout of all mongo related functions.

Data structurs

Throughout these examples we use two structs: user, address. Their definitions are:

type User struct {
	Id     string `bson:"id" json:"id"`
	Name   string `bson:"name" json:"name"`
	Last   string `bson:"last" json:"last"`
	Mobile string `bson:"mobile" json:"mobile"`
}

type Address struct {
	UserId string `bson:"userId" json:"userId"`
	Addr   string `bson:"addr" json:"addr"`
}

Insert new records

Follow are example to async insertion of records to the database


func InsertMany(gmc *gomongo.Client) error {
	user_docs := []User{
		{"1000", "name 1", "last 1", "222=3333333"},
		{"1001", "name 2", "last 2", "555=6666666"},
	}

	user_addr := []Address{
		{"1000", "my address 1"},
		{"1002", "my address 2"},
	}

	result := gomongo.InsertManySync(gmc, "users", user_docs)
	if result.Err != nil {
		return result.Err
	}
	fmt.Println("insert result", result.DbRes)

	result = gomongo.InsertManySync(gmc, "address", user_addr)
	panicOnError(result.Err)
	return result.Err
}


gmc was created in previouse example and passed as a parameter. Here we insert two documents to two different collections

As you can see we use the sync version of the methods: (InsertManySync).

If you wanted to start inserting the documents in parallel and check the result at the end, we could use the go version function, like this:


func InsertMany(gmc *gomongo.Client) error {
	user_docs := []User{
		{"1000", "name 1", "last 1", "222=3333333"},
		{"1001", "name 2", "last 2", "555=6666666"},
	}

	user_addr := []Address{
		{"1000", "my address 1"},
		{"1002", "my address 2"},
	}

	insert_user_res := gomongo.InsertManySync(gmc, "users", user_docs)
	insert_addr_res := gomongo.InsertManySync(gmc, "address", user_addr)
	
  
  if insert_user_res.Err!=nil{
    fmt.Errorf("failed to insert to users collection %v",insert_user_res.Err)
  }

  if insert_addr_res.Err!=nil{
    fmt.Errorf("failed to insert to users collection %v",insert_addr_res.Err)
  }

}


Note that in this example we use the go routing version of InsertMany (no sync endien).

This means that we first insert to users collection and immediatly insert docuemnts to address collections.

Only after we inserted all the documents we check the result of the operation. that is done by the opperation:


insert_user_res:=<-insert_user_ch
insert_addr_res:=<-insert_addr_ch

Here we drain the channels and check the result of the operation

Search for document

The advatage of using the go routing version is more apparent when we search for documents.

Say we want to fetch a user along with his address. we need to make two calls to mongo.

first call to fetch the user info and another to fetch the address. We can do this in parallel by using the go function of findOne

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


func findUserAddress(gmc *gomongo.Client, userId string) error {
	user_res := gomongo.FindOneSync[User](gmc, "users", bson.M{"id": userId})
	addr_res := gomongo.FindOneSync[Address](gmc, "address", bson.M{"userId": userId})

	if user_res.Err != nil || addr_res.Err != nil {
		return fmt.Errorf("failed to fetch user or address info %v %v", user_res.Err, addr_res.Err)
	}

	if !user_res.Found {
		return fmt.Errorf("user %s, not found", userId)
	}

	if !addr_res.Found {
		return fmt.Errorf("address of user %s, not found", userId)
	}

	fmt.Printf("Found user %v and address %v\n", user_res.Document, addr_res.Document.Addr)

	return nil
}


Note that bson.M is defined at go.mongodb.org/mongo-driver/v2/bson module.

In this example we make query to users and address in parallel. than we drain the results from the channels. We than check for errors and print the result.

Another cool feature of generic, is that you have immidiat context of the document. Is is very helpful in large scale projects.

use transaction

Use the method UseTransaction and pass it TransactionFunc. TransactionFunc is a function with the following prototyp: func(clientWithSession *Client) error

This function has a session supported gomongo.Client. This means that you can now start,commit or abort a transation for example:


func supportTransaction(gmc *gomongo.Client) error {

	user_docs := []User{
		{"1000", "name 1", "last 1", "222=3333333"},
		{"1001", "name 2", "last 2", "555=6666666"},
	}

	user_addr := []Address{
		{"1000", "my address 1"},
		{"1002", "my address 2"},
	}

	gomongo.UseTransaction(func(sessClient *Client) error{
		sessClient.StartTransation()
		insert_user_res := sessClient.InsertManySync(gmc, "users", user_docs)
		if insert_user_res.Err!=nil{
			sessClient.AbortTransation()
			return insert_user_res.Err
		}

		insert_addr_res := gomongo.InsertManySync(gmc, "address", user_addr)	
		if insert_addr_res.Err!=nil{
			sessClient.AbortTransation()
			return fmt.Errorf("failed to insert to users collection %v",insert_addr_res.Err)
  		}
	})
}



multiple calls

You can use the go func way to make several calls to the database before andling the results. See example

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


func findUserAddress(gmc *gomongo.Client, userId string) error {
	
	//run cammand parallel
	user_ch := gomongo.FindOne[User](gmc, "users", bson.M{"id": userId})
	addr_ch := gomongo.FindOne[Address](gmc, "address", bson.M{"userId": userId})

	//get the results from both channels
	user_res := <-user_ch
	addr_res := <-addr_ch

	if user_res.Err != nil || addr_res.Err != nil {
		return fmt.Errorf("failed to fetch user or address info %v %v", user_res.Err, addr_res.Err)
	}

	if !user_res.Found {
		return fmt.Errorf("user %s, not found", userId)
	}

	if !addr_res.Found {
		return fmt.Errorf("address of user %s, not found", userId)
	}

	fmt.Printf("Found user %v and address %v\n", user_res.Document, addr_res.Document.Addr)

	return nil
}


Other method

The module implement a wrapper to all major functions of mongodb, namely:

  • InsertMany
  • InsertOne
  • UpdateOne
  • UpdateMany
  • BulkWrite
  • ReplaceOne
  • FindOne
  • Find
  • Distinct
  • FindStream
  • DeleteOne
  • DeleteMany
  • CountDocuments
  • RunCommand
  • CreateIndex
  • DropIndex
  • DropAllIndex

All these method in gomongo return a none blocking channel to the struct result. Each method of gomongo has a sync method that return the struct immediatly after execution. Namely:

  • InsertManySync
  • InsertOneSync
  • UpdateOneSync
  • UpdateManySync
  • BulkWriteSync
  • ReplaceOneSync
  • FindOneSync
  • FindSync
  • DistinctSync
  • FindStreamSync
  • DeleteOneSync
  • DeleteManySync
  • CountDocumentsSync
  • RunCommandSync
  • CreateIndexSync
  • DropIndexSync
  • DropAllIndexSync

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Aggregate

func Aggregate[T any](c *Client, collName string, pipline mongo.Pipeline) chan ReadManyResult[T]

Aggregate in async way

func BulkWrite

func BulkWrite(c *Client, collName string, writeModels []mongo.WriteModel, opts ...options.Lister[options.BulkWriteOptions]) chan BulkWriteResult

func CountDocuments

func CountDocuments(c *Client, collName string, filter any, opts ...options.Lister[options.CountOptions]) chan CountResult

CountDocuments async, count the documents that return from the filter

func CreateIndex

func CreateIndex(c *Client, collName string, indexDef any, opt *options.IndexOptionsBuilder) chan IndexCreateResult

func DeleteMany

func DeleteMany(c *Client, collName string, filter any, opts ...options.Lister[options.DeleteManyOptions]) chan DeleteResult

DeleteMany delete many documents from a collection. work in async way. you need to check the result of the channel for options and details mongo deleteon command see: [https://www.mongodb.com/docs/drivers/go/current/usage-examples/deleteOne/]

func DeleteOne

func DeleteOne(c *Client, collName string, filter any, opts ...options.Lister[options.DeleteOneOptions]) chan DeleteResult

DeleteOne delete on document in a async way for options and details mongo deleteon command see: [https://www.mongodb.com/docs/drivers/go/current/usage-examples/deleteOne/]

func Distinct

func Distinct[T any](c *Client, collName string, fieldName string, filter any, opts ...options.Lister[options.DistinctOptions]) chan DistinctResult[T]

Distinct query for documents in async way

func DropAllIndex

func DropAllIndex(c *Client, collName string, opts ...options.Lister[options.DropIndexesOptions]) chan IndexDropResult

func DropIndex

func DropIndex(c *Client, collName string, indexName string, opts ...options.Lister[options.DropIndexesOptions]) chan IndexDropResult

func Find

func Find[T any](c *Client, collName string, filter any, opts ...options.Lister[options.FindOptions]) chan ReadManyResult[T]

Find query for documents in async way

func FindOne

func FindOne[T any](c *Client, collName string, filter any, opts ...options.Lister[options.FindOneOptions]) chan ReadOneResult[T]

FindOne async function that search for a single document in a collection

func FindStream

func FindStream[T any](c *Client, collName string, filter any, opts ...options.Lister[options.FindOptions]) chan ReadStreamResult[T]

Find query for documents in async way

func InsertMany

func InsertMany[T any](c *Client, collName string, documents []T, opts ...options.Lister[options.InsertManyOptions]) chan WriteManyResult

InsertMany insert many document in async way

func InsertOne

func InsertOne(c *Client, collName string, document any, opts ...options.Lister[options.InsertOneOptions]) chan WriteOneResult

func ReplaceOne

func ReplaceOne(c *Client, collName string, filter any, document any, opts ...options.Lister[options.ReplaceOptions]) chan UpdateResult

Update update a single document in an async way

func RunCommand

func RunCommand(c *Client, cmd any, opts ...options.Lister[options.RunCmdOptions]) chan CommandResult

RunCommand run database command async

func UpdateMany

func UpdateMany(c *Client, collName string, filter any, instruction any, opts ...options.Lister[options.UpdateManyOptions]) chan UpdateResult

Update update all documents matching the filter creteria in an async way

func UpdateOne

func UpdateOne(c *Client, collName string, filter any, instruction any, opts ...options.Lister[options.UpdateOneOptions]) chan UpdateResult

Update update a single document in an async way

Types

type BulkWriteResult

type BulkWriteResult struct {
	Err   error
	DbRes *mongo.BulkWriteResult
}

func BulkWriteSync

func BulkWriteSync(c *Client, collName string, writeModels []mongo.WriteModel, opts ...options.Lister[options.BulkWriteOptions]) BulkWriteResult

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(host string, database string, connTimeout ...time.Duration) *Client

NewClient return a pointer to gomongo.Client that is used to communicate the Mongodb

Parameters:

host: a host name in the form of mongodb://host:port. Fool explanation can be found at [https://www.mongodb.com/docs/drivers/go/current/fundamentals/connections/connection-guide/]
database: The client is aim to work with a single database. so you can set its name at the initialization stage.
connTimeout: The timeout of the operations against the database. If you do not set it will set to the default of 10 seconds

func (*Client) Disconnect

func (c *Client) Disconnect(ctx context.Context) error

func (*Client) GetMongoClient

func (c *Client) GetMongoClient() (*mongo.Client, error)

func (*Client) Ping

func (c *Client) Ping() bool

func (*Client) UseTransaction

func (c *Client) UseTransaction(transactionFunc TransactionFunc) error

type CommandResult

type CommandResult struct {
	DbRes *mongo.SingleResult
	Err   error
}

func RunCommandSync

func RunCommandSync(c *Client, cmd any, opts ...options.Lister[options.RunCmdOptions]) CommandResult

RunCommand run a command on the database

type CountResult

type CountResult struct {
	Count int64
	Err   error
}

func CountDocumentsSync

func CountDocumentsSync(c *Client, collName string, filter any, opts ...options.Lister[options.CountOptions]) CountResult

CountDocuments count the documents that return from the filter

type DeleteResult

type DeleteResult struct {
	DelCount int64
	Err      error
}

func DeleteManySync

func DeleteManySync(c *Client, collName string, filter any, opts ...options.Lister[options.DeleteManyOptions]) DeleteResult

DeleteManySync delete many documents from a collection. work in a sync way for options and details mongo deleteon command see: [https://www.mongodb.com/docs/drivers/go/current/usage-examples/deleteOne/]

func DeleteOneSync

func DeleteOneSync(c *Client, collName string, filter any, opts ...options.Lister[options.DeleteOneOptions]) DeleteResult

DeleteOneSync delete on document base on the filter string for options and details mongo deleteon command see: [https://www.mongodb.com/docs/drivers/go/current/usage-examples/deleteOne/]

type DistinctResult

type DistinctResult[T any] struct {
	Values []T
	Err    error
}

func DistinctSync

func DistinctSync[T any](c *Client, collName string, fieldName string, filter any, opts ...options.Lister[options.DistinctOptions]) DistinctResult[T]

type IndexCreateResult

type IndexCreateResult struct {
	IndexName string
	Err       error
}

func CreateIndexSync

func CreateIndexSync(c *Client, collName string, indexDef any, idxOpt *options.IndexOptionsBuilder) IndexCreateResult

type IndexDropResult

type IndexDropResult struct {
	Doc bson.Raw
	Err error
}

func DropAllIndexSync

func DropAllIndexSync(c *Client, collName string, opts ...options.Lister[options.DropIndexesOptions]) IndexDropResult

func DropIndexSync

func DropIndexSync(c *Client, collName string, name string, opts ...options.Lister[options.DropIndexesOptions]) IndexDropResult

type IndexListResult

type IndexListResult struct {
	Result []any
	Err    error
}

func ListIndexSync

func ListIndexSync(c *Client, collName string, opts ...options.Lister[options.ListIndexesOptions]) IndexListResult

type ReadManyResult

type ReadManyResult[T any] struct {
	Documents []T
	Err       error
}

func AggregateSync

func AggregateSync[T any](c *Client, collName string, pipline mongo.Pipeline) ReadManyResult[T]

func FindSync

func FindSync[T any](c *Client, collName string, filter any, opts ...options.Lister[options.FindOptions]) ReadManyResult[T]

FindSync query for documents in a sync way

type ReadOneResult

type ReadOneResult[T any] struct {
	Found    bool
	Document T
	Err      error
	DbRes    *mongo.SingleResult
}

func FindOneSync

func FindOneSync[T any](c *Client, collName string, filter any, opts ...options.Lister[options.FindOneOptions]) ReadOneResult[T]

FindOneSync sync version of searching for a single document in a collection

type ReadStreamResult

type ReadStreamResult[T any] struct {
	DocumentStream chan ReadOneResult[T]
	Err            error
}

func FindStreamSync

func FindStreamSync[T any](c *Client, collName string, filter any, opts ...options.Lister[options.FindOptions]) ReadStreamResult[T]

type TransactionFunc

type TransactionFunc func(client *Client) (TransactionResult, error)

TransactionFunc is called in a transaction session If all is well the function should return true and error should be nill other wise return false. if you want to pass an error to the calling

type TransactionResult

type TransactionResult string
const (
	TransactionResultCommit TransactionResult = "commit"
	TransactionResultAbort  TransactionResult = "abort"
)

type UpdateResult

type UpdateResult struct {
	DbRes *mongo.UpdateResult
	Err   error
}

func ReplaceOneSync

func ReplaceOneSync(c *Client, collName string, filter any, document any, opts ...options.Lister[options.ReplaceOptions]) UpdateResult

func UpdateManySync

func UpdateManySync(c *Client, collName string, filter any, instruction any, opts ...options.Lister[options.UpdateManyOptions]) UpdateResult

func UpdateOneSync

func UpdateOneSync(c *Client, collName string, filter any, instruction any, opts ...options.Lister[options.UpdateOneOptions]) UpdateResult

type WriteManyResult

type WriteManyResult struct {
	DbRes *mongo.InsertManyResult
	Err   error
}

func InsertManySync

func InsertManySync[T any](c *Client, collName string, documents []T, opts ...options.Lister[options.InsertManyOptions]) WriteManyResult

**************************************************************************************************************** **************************************************************************************************************** ****************************************************************************************************************

SYNC methods

**************************************************************************************************************** **************************************************************************************************************** ******************************************************************************************************************

type WriteOneResult

type WriteOneResult struct {
	DbRes *mongo.InsertOneResult
	Err   error
}

func InsertOneSync

func InsertOneSync(c *Client, collName string, document any, opts ...options.Lister[options.InsertOneOptions]) WriteOneResult

InsertOneSync insert one document to collection.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL