cosmosdbsql

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Oct 2, 2022 License: MIT Imports: 11 Imported by: 1

README

godal/cosmosdbsql

PkgGoDev codecov

Generic Azure Cosmos DB DAO implementation using database/sql interface.

Guideline

General

  • DAOs must implement IGenericDao.GdaoCreateFilter(string, IGenericBo) FilterOpt.

Use GenericDaoCosmosdb (and godal.IGenericBo) directly

  • Define a DAO struct that extends GenericDaoCosmosdb and implements IGenericDao.GdaoCreateFilter(string, IGenericBo) FilterOpt.
  • Configure either {collection-name:path-to-fetch-partition_key-value-from-genericbo} via GenericDaoCosmosdb.CosmosSetPkGboMapPath or {collection-name:path-to-fetch-partition_key-value-from-dbrow} via GenericDaoCosmosdb.CosmosSetPkRowMapPath.
  • Optionally, configure {collection-name:path-to-fetch-id-value-from-genericbo} via GenericDaoCosmosdb.CosmosSetIdGboMapPath.
  • Optionally, create a helper function to create DAO instances.

Implement custom database/sql business DAOs and BOs

  • Define and implement the business DAO (Note: DAOs must implement IGenericDao.GdaoCreateFilter(string, IGenericBo) FilterOpt).
  • Define functions to transform godal.IGenericBo to business BO and vice versa.
  • Optionally, create a helper function to create DAO instances.

Partition key (PK) is crucial to CosmosDB. PK value is needed in almost all document related operations. Hence, it's important to be able to extract PK value from BO. If using or extending GenericDaoCosmosdb, configure either {collection-name:path-to-fetch-partition_key-value-from-genericbo} via GenericDaoCosmosdb.CosmosSetPkGboMapPath or {collection-name:path-to-fetch-partition_key-value-from-dbrow} via GenericDaoCosmosdb.CosmosSetPkRowMapPath.

Examples: see examples and examples_sta.

This package explicitly uses github.com/btnguyen2k/gocosmos as the SQL driver for Azure Cosmos DB.

Documentation

Overview

Package cosmosdbsql provides a generic Azure Cosmos DB implementation of godal.IGenericDao using database/sql interface.

General guideline:

  • DAOs must implement IGenericDao.GdaoCreateFilter(string, IGenericBo) FilterOpt.

Guideline: Use GenericDaoCosmosdb (and godal.IGenericBo) directly

  • Define a DAO struct that implements IGenericDao.GdaoCreateFilter(string, IGenericBo) FilterOpt.

  • Configure either {collection-name:path-to-fetch-partition_key-value-from-genericbo} (via GenericDaoCosmosdb.CosmosSetPkGboMapPath) or {collection-name:path-to-fetch-partition_key-value-from-dbrow} (via GenericDaoCosmosdb.CosmosSetPkRowMapPath).

  • Optionally, configure {collection-name:path-to-fetch-id-value-from-genericbo} via GenericDaoCosmosdb.CosmosSetIdGboMapPath.

  • Optionally, create a helper function to create DAO instances.

    // Remember to import the database driver, the only supported/available driver for now is "github.com/btnguyen2k/gocosmos". import ( "github.com/btnguyen2k/consu/reddo" "github.com/btnguyen2k/godal" godalcosmosdb "github.com/btnguyen2k/godal/cosmosdbsql" promsql "github.com/btnguyen2k/prom/sql"

    _ "github.com/btnguyen2k/gocosmos" )

    type myGenericDaoCosmosdb struct { *godalcosmosdb.GenericDaoCosmosdb }

    // GdaoCreateFilter implements godal.IGenericDao.GdaoCreateFilter. func (dao *myGenericDaoCosmosdb) GdaoCreateFilter(collection string, bo godal.IGenericBo) godal.FilterOpt { id := bo.GboGetAttrUnsafe(fieldId, reddo.TypeString) return &godal.FilterOptFieldOpValue{FieldName: fieldId, Operator: godal.FilterOpEqual, Value: id} }

    // newGenericDaoCosmosdb is helper function to create myGenericDaoCosmosdb instances. func newGenericDaoCosmosdb(sqlc *promsql.SqlConnect) godal.IGenericDao { rowMapper := godalcosmosdb.GenericRowMapperCosmosdbInstance dao := &myGenericDaoCosmosdb{} dao.GenericDaoCosmosdb = godalcosmosdb.NewGenericDaoCosmosdb(sqlc, godal.NewAbstractGenericDao(dao)) dao.SetSqlFlavor(sql.FlavorCosmosDb).SetRowMapper(rowMapper) dao.SetTxModeOnWrite(false) dao.CosmosSetPkGboMapPath(map[string]string{collectionName: fieldPk}) return dao }

    Since Azure Cosmos DB is schema-less, GenericRowMapperCosmosdbInstance should be sufficient.

    txModeOnWrite should be disabled as btnguyen2k/gocosmosdb driver does not currently support transaction!

Guideline: Implement custom Azure Cosmos DB business DAOs and BOs

  • Define and implement the business DAO (Note: DAOs must implement IGenericDao.GdaoCreateFilter(string, IGenericBo) FilterOpt).

  • Define functions to transform godal.IGenericBo to business BO and vice versa.

  • Optionally, create a helper function to create DAO instances.

    // Remember to import the database driver, the only supported/available driver for now is "github.com/btnguyen2k/gocosmos". import ( "github.com/btnguyen2k/consu/reddo" "github.com/btnguyen2k/godal" godalcosmosdb "github.com/btnguyen2k/godal/cosmosdbsql" promsql "github.com/btnguyen2k/prom/sql"

    _ "github.com/btnguyen2k/gocosmos" )

    // BoApp defines business object app type BoApp struct { Id string `json:"id"` Description string `json:"desc"` Value int `json:"val"` Pk string `json:"pk"` // it's a good idea to have a dedicated field for partition key }

    func (app *BoApp) ToGbo() godal.IGenericBo { gbo := godal.NewGenericBo()

    // method 1: populate attributes one by one gbo.GboSetAttr("id" , app.Id) gbo.GboSetAttr("desc", app.Description) gbo.GboSetAttr("val" , app.Value) gbo.GboSetAttr("pk" , app.Pk)

    // method 2: transfer all attributes at once if err := gbo.GboImportViaJson(app); err!=nil { panic(err) }

    return gbo }

    func NewBoAppFromGbo(gbo godal.IGenericBo) *BoApp { app := BoApp{}

    // method 1: populate attributes one by one app.Id = gbo.GboGetAttrUnsafe("id", reddo.TypeString).(string) app.Description = gbo.GboGetAttrUnsafe("desc", reddo.TypeString).(string) app.Value = int(gbo.GboGetAttrUnsafe("val", reddo.TypeInt).(int64)) app.Pk = gbo.GboGetAttrUnsafe("pk", reddo.TypeString).(string)

    // method 2: transfer all attributes at once if err := gbo.GboTransferViaJson(&app); err!=nil { panic(err) }

    return &app }

    // DaoAppCosmosdb is Azure CosmosDB-implementation of business dao. type DaoAppCosmosdb struct { *godalcosmosdb.GenericDaoCosmosdb collectionName string }

    // NewDaoAppCosmosdb is helper function to create DaoAppCosmosdb instances. func NewDaoAppCosmosdb(sqlc *promsql.SqlConnect, collectionName string) *DaoAppCosmosdb { rowMapper := GenericRowMapperCosmosdbInstance dao := &DaoAppCosmosdb{collectionName: collectionName} dao.GenericDaoCosmosdb = godalcosmosdb.NewGenericDaoCosmosdb(sqlc, godal.NewAbstractGenericDao(dao)) dao.SetSqlFlavor(sql.FlavorCosmosDb).SetRowMapper(rowMapper) dao.SetTxModeOnWrite(false) dao.CosmosSetPkGboMapPath(map[string]string{"*": fieldPk}) return dao }

    Since Azure Cosmos DB is schema-less, GenericRowMapperCosmosdbInstance should be sufficient.

    txModeOnWrite should be disabled as btnguyen2k/gocosmosdb driver does not currently support transaction!

    Partition key (PK) is crucial to CosmosDB. PK value is needed in almost all document related operations. Hence, it's important to be able to extract PK value from BO. If using or extending GenericDaoCosmosdb, configure either {collection-name:path-to-fetch-partition_key-value-from-genericbo} (via GenericDaoCosmosdb.CosmosSetPkGboMapPath) or {collection-name:path-to-fetch-partition_key-value-from-dbrow} (via GenericDaoCosmosdb.CosmosSetPkRowMapPath).

See more examples in 'examples' directory on project's GitHub: https://github.com/btnguyen2k/godal/tree/master/examples

To create SqlConnect instances, see package github.com/btnguyen2k/prom/sql

Index

Constants

This section is empty.

Variables

View Source
var (
	// GenericRowMapperCosmosdbInstance is a pre-created instance of GenericRowMapperCosmosdb that is ready to use.
	GenericRowMapperCosmosdbInstance godal.IRowMapper = &GenericRowMapperCosmosdb{}
)

Functions

This section is empty.

Types

type GenericDaoCosmosdb

type GenericDaoCosmosdb struct {
	godalsql.IGenericDaoSql
	// contains filtered or unexported fields
}

GenericDaoCosmosdb is Azure Cosmos DB implementation of godal.IGenericDao.

Function implementations (n = No, y = Yes, i = inherited):

  • (n) GdaoCreateFilter(collectionName string, bo godal.IGenericBo) godal.FilterOpt
  • (y) GdaoDelete(collectionName string, bo godal.IGenericBo) (int, error)
  • (y) GdaoDeleteMany(collectionName string, filter godal.FilterOpt) (int, error)
  • (y) GdaoFetchOne(collectionName string, filter godal.FilterOpt) (godal.IGenericBo, error)
  • (y) GdaoFetchMany(collectionName string, filter godal.FilterOpt, sorting *godal.SortingOpt, startOffset, numItems int) ([]godal.IGenericBo, error)
  • (y) GdaoCreate(collectionName string, bo godal.IGenericBo) (int, error)
  • (y) GdaoUpdate(collectionName string, bo godal.IGenericBo) (int, error)
  • (y) GdaoSave(collectionName string, bo godal.IGenericBo) (int, error)

Available: since v0.3.0

func NewGenericDaoCosmosdb

func NewGenericDaoCosmosdb(sqlConnect *sql.SqlConnect, agdao *godal.AbstractGenericDao) *GenericDaoCosmosdb

NewGenericDaoCosmosdb constructs a new Azure Cosmos DB implementation of 'godal.IGenericDao'.

func (*GenericDaoCosmosdb) CosmosGetId

func (dao *GenericDaoCosmosdb) CosmosGetId(collectionName string, bo godal.IGenericBo) string

CosmosGetId extracts and returns ID value from a (generic) BO.

If a mapping {collection-name:path-to-fetch-id-value-from-genericbo} has been specified, this function looks up the "id" value directly from the mapping. If the lookup is not successful, or there is no such mapping specified, the BO is then transformed to row (via the row-mapper) and the value of row's "id" field is returned.

See CosmosSetIdGboMapPath.

func (*GenericDaoCosmosdb) CosmosGetIdGboMapPath

func (dao *GenericDaoCosmosdb) CosmosGetIdGboMapPath() map[string]string

CosmosGetIdGboMapPath gets the mapping {collection-name:path-to-fetch-id-value-from-genericbo}.

It is optional but highly recommended to specify such a mapping for performance reason. If no such mapping specified, extracting ID from a (generic) BO needs to go through a two-step process, which often imposes a negative impact on performance.

Collection-name is "*" means "match any collection".

func (*GenericDaoCosmosdb) CosmosGetPk

func (dao *GenericDaoCosmosdb) CosmosGetPk(collectionName string, bo godal.IGenericBo) interface{}

CosmosGetPk extracts and returns partition key value from a BO.

Firstly, the mapping {collection-name:path-to-fetch-partition_key-value-from-genericbo} is used to look up the PK value from the BO. If the lookup is not successful, the mapping {collection-name:path-to-fetch-partition_key-value-from-dbrow} is then used for lookup.

Collection-name is "*" means "match any collection".

func (*GenericDaoCosmosdb) CosmosGetPkGboMapPath

func (dao *GenericDaoCosmosdb) CosmosGetPkGboMapPath() map[string]string

CosmosGetPkGboMapPath gets the mapping {collection-name:path-to-fetch-partition_key-value-from-genericbo}.

Note: at least one of {collection-name:path-to-fetch-partition_key-value-from-genericbo} and {collection-name:path-to-fetch-partition_key-value-from-dbrow} mappings must be configured. If not, client may encounter error "PartitionKey extracted from document doesn't match the one specified in the header".

Collection-name is "*" means "match any collection".

func (*GenericDaoCosmosdb) CosmosGetPkRowMapPath

func (dao *GenericDaoCosmosdb) CosmosGetPkRowMapPath() map[string]string

CosmosGetPkRowMapPath gets the mapping {collection-name:path-to-fetch-partition_key-value-from-dbrow}.

Note: at least one of {collection-name:path-to-fetch-partition_key-value-from-genericbo} and {collection-name:path-to-fetch-partition_key-value-from-dbrow} mappings must be configured. If not, client may encounter error "PartitionKey extracted from document doesn't match the one specified in the header".

Collection-name is "*" means "match any collection".

func (*GenericDaoCosmosdb) CosmosSetIdGboMapPath

func (dao *GenericDaoCosmosdb) CosmosSetIdGboMapPath(idGboPathMap map[string]string) *GenericDaoCosmosdb

CosmosSetIdGboMapPath sets the mapping {collection-name:path-to-fetch-id-value-from-genericbo}.

It is optional but highly recommended to specify such a mapping for performance reason. If no such mapping specified, extracting ID from a (generic) BO needs to go through a two-step process, which often imposes a negative impact on performance.

Collection-name is "*" means "match any collection".

func (*GenericDaoCosmosdb) CosmosSetPkGboMapPath

func (dao *GenericDaoCosmosdb) CosmosSetPkGboMapPath(pkGboPathMap map[string]string) *GenericDaoCosmosdb

CosmosSetPkGboMapPath sets the mapping {collection-name:path-to-fetch-partition_key-value-from-genericbo}.

Note: at least one of {collection-name:path-to-fetch-partition_key-value-from-genericbo} and {collection-name:path-to-fetch-partition_key-value-from-dbrow} mappings must be configured. If not, client may encounter error "PartitionKey extracted from document doesn't match the one specified in the header".

Collection-name is "*" means "match any collection".

func (*GenericDaoCosmosdb) CosmosSetPkRowMapPath

func (dao *GenericDaoCosmosdb) CosmosSetPkRowMapPath(pkRowPathMap map[string]string) *GenericDaoCosmosdb

CosmosSetPkRowMapPath sets the mapping {collection-name:path-to-fetch-partition_key-value-from-dbrow}.

Note: at least one of {collection-name:path-to-fetch-partition_key-value-from-genericbo} and {collection-name:path-to-fetch-partition_key-value-from-dbrow} mappings must be configured. If not, client may encounter error "PartitionKey extracted from document doesn't match the one specified in the header".

Collection-name is "*" means "match any collection".

func (*GenericDaoCosmosdb) GdaoCreate

func (dao *GenericDaoCosmosdb) GdaoCreate(collectionName string, bo godal.IGenericBo) (int, error)

GdaoCreate implements godal.IGenericDao.GdaoCreate.

func (*GenericDaoCosmosdb) GdaoCreateWithTx

func (dao *GenericDaoCosmosdb) GdaoCreateWithTx(ctx context.Context, tx *gosql.Tx, collectionName string, bo godal.IGenericBo) (int, error)

GdaoCreateWithTx is database/sql variant of GdaoCreate.

func (*GenericDaoCosmosdb) GdaoDelete

func (dao *GenericDaoCosmosdb) GdaoDelete(collectionName string, bo godal.IGenericBo) (int, error)

GdaoDelete implements godal.IGenericDao.GdaoDelete.

func (*GenericDaoCosmosdb) GdaoDeleteMany

func (dao *GenericDaoCosmosdb) GdaoDeleteMany(collectionName string, filter godal.FilterOpt) (int, error)

GdaoDeleteMany implements godal.IGenericDao.GdaoDeleteMany.

func (*GenericDaoCosmosdb) GdaoDeleteManyWithTx

func (dao *GenericDaoCosmosdb) GdaoDeleteManyWithTx(ctx context.Context, tx *gosql.Tx, collectionName string, filter godal.FilterOpt) (int, error)

GdaoDeleteManyWithTx is database/sql variant of GdaoDeleteMany.

Note: this function firstly fetches all matched documents and then delete them one by one.

func (*GenericDaoCosmosdb) GdaoDeleteWithTx

func (dao *GenericDaoCosmosdb) GdaoDeleteWithTx(ctx context.Context, tx *gosql.Tx, collectionName string, bo godal.IGenericBo) (int, error)

GdaoDeleteWithTx is database/sql variant of GdaoDelete.

func (*GenericDaoCosmosdb) GdaoFetchMany

func (dao *GenericDaoCosmosdb) GdaoFetchMany(collectionName string, filter godal.FilterOpt, sorting *godal.SortingOpt, fromOffset, numRows int) ([]godal.IGenericBo, error)

GdaoFetchMany implements godal.IGenericDao.GdaoFetchMany.

func (*GenericDaoCosmosdb) GdaoFetchManyWithTx

func (dao *GenericDaoCosmosdb) GdaoFetchManyWithTx(ctx context.Context, tx *gosql.Tx, collectionName string, filter godal.FilterOpt, sorting *godal.SortingOpt, fromOffset, numRows int) ([]godal.IGenericBo, error)

GdaoFetchManyWithTx is database/sql variant of GdaoFetchMany.

func (*GenericDaoCosmosdb) GdaoFetchOne

func (dao *GenericDaoCosmosdb) GdaoFetchOne(collectionName string, filter godal.FilterOpt) (godal.IGenericBo, error)

GdaoFetchOne implements godal.IGenericDao.GdaoFetchOne.

func (*GenericDaoCosmosdb) GdaoFetchOneWithTx

func (dao *GenericDaoCosmosdb) GdaoFetchOneWithTx(ctx context.Context, tx *gosql.Tx, collectionName string, filter godal.FilterOpt) (godal.IGenericBo, error)

GdaoFetchOneWithTx is database/sql variant of GdaoFetchOne.

func (*GenericDaoCosmosdb) GdaoSave

func (dao *GenericDaoCosmosdb) GdaoSave(collectionName string, bo godal.IGenericBo) (int, error)

GdaoSave implements godal.IGenericDao.GdaoSave.

func (*GenericDaoCosmosdb) GdaoSaveWithTx

func (dao *GenericDaoCosmosdb) GdaoSaveWithTx(ctx context.Context, tx *gosql.Tx, collectionName string, bo godal.IGenericBo) (int, error)

GdaoSaveWithTx is extended-implementation of godal.IGenericDao.GdaoSave.

func (*GenericDaoCosmosdb) GdaoUpdate

func (dao *GenericDaoCosmosdb) GdaoUpdate(collectionName string, bo godal.IGenericBo) (int, error)

GdaoUpdate implements godal.IGenericDao.GdaoUpdate.

func (*GenericDaoCosmosdb) GdaoUpdateWithTx

func (dao *GenericDaoCosmosdb) GdaoUpdateWithTx(ctx context.Context, tx *gosql.Tx, collectionName string, bo godal.IGenericBo) (int, error)

GdaoUpdateWithTx is database/sql variant of GdaoUpdate.

func (*GenericDaoCosmosdb) IsErrorDuplicatedEntry

func (dao *GenericDaoCosmosdb) IsErrorDuplicatedEntry(err error) bool

IsErrorDuplicatedEntry checks if the error was caused by document conflicting in collection.

type GenericRowMapperCosmosdb

type GenericRowMapperCosmosdb struct {
}

GenericRowMapperCosmosdb is a generic implementation of godal.IRowMapper for Azure Cosmos DB.

Implementation rules:

  • ToRow : transform godal.IGenericBo "as-is" to map[string]interface{}.
  • ToBo : expects input is a map[string]interface{}, or JSON data (string or array/slice of bytes), transforms input to godal.IGenericBo via JSON unmarshalling.
  • ColumnsList : return []string{"*"} (CosmosDB is schema-free, hence column-list is not used).
  • ToDbColName : return the input field name "as-is".
  • ToBoFieldName: return the input column name "as-is".

Available: since v0.3.0

func (*GenericRowMapperCosmosdb) ColumnsList

func (mapper *GenericRowMapperCosmosdb) ColumnsList(_ string) []string

ColumnsList implements godal.IRowMapper.ColumnsList.

This function returns []string{"*"} since CosmosDB is schema-free (hence column-list is not used).

func (*GenericRowMapperCosmosdb) ToBo

func (mapper *GenericRowMapperCosmosdb) ToBo(collectionName string, row interface{}) (godal.IGenericBo, error)

ToBo implements godal.IRowMapper.ToBo.

This function expects input to be a map[string]interface{}, or JSON data (string or array/slice of bytes), transforms it to godal.IGenericBo via JSON unmarshalling. Field names are kept intact.

func (*GenericRowMapperCosmosdb) ToBoFieldName added in v0.5.0

func (mapper *GenericRowMapperCosmosdb) ToBoFieldName(_, colName string) string

ToBoFieldName implements godal.IRowMapper.ToBoFieldName.

This function returns the input column name "as-is".

func (*GenericRowMapperCosmosdb) ToDbColName added in v0.5.0

func (mapper *GenericRowMapperCosmosdb) ToDbColName(_, fieldName string) string

ToDbColName implements godal.IRowMapper.ToDbColName.

This function returns the input field name "as-is".

func (*GenericRowMapperCosmosdb) ToRow

func (mapper *GenericRowMapperCosmosdb) ToRow(_ string, bo godal.IGenericBo) (interface{}, error)

ToRow implements godal.IRowMapper.ToRow.

This function transforms godal.IGenericBo to map[string]interface{}. Field names are kept intact.

Jump to

Keyboard shortcuts

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