GithubHelp home page GithubHelp logo

mongofunc's Introduction

Mongofunc

mongofunc is a Go package that provides a fluent query builder for MongoDB. It allows constructing MongoDB find queries using a chained syntax.

The library aims to make querying MongoDB easy and intuitive for Go developers.

Table of Contents

Content:

Introduction

With mongofunc, you can write MongoDB find queries using chained method calls instead of constructing nested documents. This results in query code that is:

  • Clean - Query logic reads clearly from top to bottom
  • Composable - Combine and reuse query conditions easily
  • Typed - Fully integrated with Go's type system

For example:

query := moper.Query().
           Greater("age", 21).
           Equal("status", "active")

The above query filters for age greater than 21 and status equal to "active".

mongofunc handles converting the chained calls to proper MongoDB query filter documents under the hood.

Getting Started

Install the package:

$ go get github.com/func25/mongofunc/v2

Import it in your code:

import "github.com/func25/mongofunc/v2/moper"

You can find full example code at Using Commands

Moper: Building Queries

Query

To start a new query:

query := moper.Query()

Start chaining query methods to build your query, let's find all users name Sarah and age greater than 18:

filter := query.Equal("name", "Sarah").
                Greater("age", 18)

The package provides functions for MongoDB queries to perform time-based comparisons on documents.

filter := moper.Query().
                EqualGreaterTime("expired", time.Now())

Update

Let's take a complex update command as an example:

update := moper.Query().
	Inc("age", 1).
	Push("hobbies", "guitar").
	Unset("addresses.0").
	Set("addresses.1", bson.M{
		"street": "123 Main St",
		"city":   "Springfield",
	})

Support simple aggregation:

intArr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

matchStage := moper.Query().MatchD(moper.Query().InArray("damage", intArr))
groupStage := moper.Query().Group(
	moper.P{K: "_id", V: nil},
	moper.P{K: "total", V: moper.Query().Sum("damage")},
)

req := &mocom.AggregationRequest[Hero]{
	Pipeline: []moper.D{matchStage, groupStage},
	Options:  []*options.AggregateOptions{},
}

Let's skim through some query methods:

  • Equal(fieldName, value): Adds an equality filter to the pipeline.
  • NotEqual(fieldName, value): Adds a non-equality filter to the pipeline.
  • InEll(fieldName, value...): Adds an "in" filter to the pipeline.
  • NotInEll(fieldName, value...): Adds a "not in" filter to the pipeline.
  • EqualLess(fieldName, value): Adds a "less than or equal" filter to the pipeline.
  • EqualGreater(fieldName, value): Adds a "greater than or equal" filter to the pipeline.
  • Less(fieldName, value): Adds a "less than" filter to the pipeline.
  • Greater(fieldName, value): Adds a "greater than" filter to the pipeline.
  • Exists(fieldName, exist): Adds an "exists" filter to the pipeline.
  • Or(filters...): Adds an "or" filter to the pipeline
  • ...

Mocom: MongoClient Commands

mocom is a Go package that provides a simple MongoDB client wrapper to handle MongoDB connections and collections. It offers convenient functions to connect to a MongoDB server, set the default database, retrieve the client, and get collections for reading and writing.

Connect with mocom

Use the Connect function to establish a connection to the MongoDB server:

ctx := context.Background()
uri := "mongodb://localhost:27017/?w=majority&retryWrites=false"
dbName := "your-database-name"

if err := mocom.Connect(ctx, uri, dbName); err != nil {
    log.Fatal("Failed to connect to MongoDB:", err)
}

// Now you can perform database operations using the mocom and moper package

Working with Collections

You can now use the package to retrieve MongoDB collections for reading and writing:

// Get a collection for reading with read preference "Nearest"
readColl := mocom.CollRead("your-collection-name")

// Get a collection for writing with read preference "Primary"
writeColl := mocom.CollWrite("your-collection-name")

Using commands

Mocom supports CRUD operations with moper commands, let's check a fulll example:

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/func25/mongofunc/v2/mocom"
	"github.com/func25/mongofunc/v2/moper"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type User struct {
	mocom.ObjectID `json:",inline" bson:",inline"`
	Username       string    `json:"username" bson:"username"`
	Email          string    `json:"email" bson:"email"`
	Age            int       `json:"age" bson:"age"`
	CreatedAt      time.Time `json:"createdAt" bson:"createdAt"`
}

// This function is needed to satisfy the mocom.Model interface, so we can use it with mocom generic functions
func (u User) CollName() string {
	return "users"
}

func main() {
	// Connect to MongoDB
	ctx, cancel := context.WithTimeout(context.Background(), 1000*time.Second)
	defer cancel()

	uri := "mongodb://localhost:27017/?w=majority&retryWrites=false"
	dbName := "exampledb"

	err := mocom.Connect(ctx, uri, dbName)
	if err != nil {
		fmt.Println("Failed to connect to MongoDB:", err)
		return
	}

	// Perform CRUD operations with the User model
	user := User{
		Username:  "john_doe",
		Email:     "[email protected]",
		Age:       30,
		CreatedAt: time.Now(),
	}

	// Create a new user using mocom.Create[User] syntax
	insertedID, err := mocom.CreateT[User](ctx, user)
	if err != nil {
		fmt.Println("Failed to create user:", err)
		return
	}

	fmt.Println("User created with ID:", insertedID)

	// Find all users using moper package
	matchStage := moper.Query().MatchD(moper.Query().InArray("age", []int{30, 40}))
	groupStage := moper.Query().Group(moper.P{K: "_id", V: nil}, moper.P{K: "total", V: moper.Query().Sum("age")})

	// Aggregate the users with matching age and calculate the total age using mocom
	aggRequest := &mocom.AggregationRequest{
		Pipeline: []moper.D{matchStage, groupStage},
		Options:  []*options.AggregateOptions{},
	}

	aggResult, err := mocom.AggregateT[User](ctx, aggRequest)
	if err != nil {
		fmt.Println("Failed to aggregate users:", err)
		return
	}

	fmt.Println("Users aggregated:", aggResult)

	// Update the user's email using moper package
	filter := moper.Query().Equal("_id", insertedID)
	update := moper.Query().Set(moper.Pr("email", "[email protected]"))
	_, err = mocom.UpdateOneT[User](ctx, filter, update)
	if err != nil {
		fmt.Println("Failed to update user:", err)
		return
	}

	fmt.Println("User updated")

	// Find a user by ID using mocom
	foundUser, err := mocom.FindOne[User](ctx, filter)
	if err != nil {
		fmt.Println("Failed to find user by ID:", err)
		return
	}

	fmt.Println("User found by ID:", foundUser)

	// Delete the user using mocom
	_, err = mocom.DeleteOneT[User](ctx, filter)
	if err != nil {
		fmt.Println("Failed to delete user:", err)
		return
	}

	fmt.Println("User deleted")
}

Transaction

Nested transaction

mocom provides support for nested transactions to help you manage complex transactional workflows. If a nested transaction is detected, the Tx and TxOptimal functions will execute the transaction with the provided context.

Tx()

The Tx function executes a MongoDB transaction based on the provided configuration (cfg) and context (ctx). It allows you to perform a series of operations in a transactional manner, ensuring that either all operations succeed, or none of them are applied.

result, err := mocom.Tx(ctx, TransactionConfig{
    SessConfig: options.Session(),
    Options:    options.Transaction(),
    Func: func(ctx mongo.SessionContext) (interface{}, error) {
        // Your transaction logic here
        // e.g., insert, update, or delete operations
        // e.g., perform multiple actions as a single atomic transaction
    },
})

TxOptimal()

The TxOptimal function provides an optimal MongoDB transaction without read operations. It is suitable for scenarios where you only need to perform write operations, ensuring atomicity and consistency across multiple writes.

result, err := mocom.TxOptimal(ctx, func(ctx mongo.SessionContext) (interface{}, error) {
    // Your transaction logic here
    // e.g., insert, update, or delete operations
    // e.g., write operations without read operations
})

License

mongofunc is provided under the MIT License. Use it freely in your Go applications.

Let me know if you would like any changes to the README. I'm happy to help make it as useful as possible!

mongofunc's People

Contributors

qphuongl avatar func25 avatar

Stargazers

Edward Fernandes avatar Feng avatar 虫子樱桃 avatar  avatar Iwan Lebron avatar Tinh avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.