orm

package module
v1.1.17-0...-677f2db Latest Latest
Warning

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

Go to latest
Published: Apr 11, 2021 License: MIT Imports: 32 Imported by: 0

README

orm

codecov Go Report Card MIT license

ORM that delivers support for full stack data access:

  • MySQL - for relational data
  • Redis - for NoSQL in memory shared cache
  • Elastic Search - for full text search
  • Redis Search - for full text and in-memory search
  • Local Cache - in memory local (not shared) cache
  • ClickHouse - time series database

Menu:

Configuration

First you need to define Registry object and register all connection pools to MySQL, Redis and local cache. Use this object to register queues, and entities. You should create this object once when application starts.

package main

import "github.com/latolukasz/orm"

func main() {

    registry := &Registry{}

    /*MySQL */
    registry.RegisterMySQLPool("root:root@tcp(localhost:3306)/database_name?limit_connections=10") // you should define max connections, default 100
    //optionally you can define pool name as second argument
    registry.RegisterMySQLPool("root:root@tcp(localhost:3307)/database_name", "second_pool")
    registry.DefaultEncoding("utf8") //optional, default is utf8mb4

    /* Redis */
    registry.RegisterRedis("localhost:6379", 0)
    //optionally you can define pool name as second argument
    registry.RegisterRedis("localhost:6379", 1, "second_pool")

    /* Redis sentinel */
    registry.RegisterRedisSentinel("mymaster", 0, []string{":26379", "192.23.12.33:26379", "192.23.12.35:26379"})
    // redis database number set to 2
    registry.RegisterRedisSentinel("mymaster", 2, []string{":26379", "192.23.12.11:26379", "192.23.12.12:26379"}, "second_pool") 

    /* Local cache (in memory) */
    registry.RegisterLocalCache(1000) //you need to define cache size
    //optionally you can define pool name as second argument
    registry.RegisterLocalCache(100, "second_pool")

    /* Redis used to handle locks (explained later) */
    registry.RegisterRedis("localhost:6379", 4, "lockers_pool")
    registry.RegisterLocker("default", "lockers_pool")

    /* ElasticSearch */
    registry.RegisterElastic("http://127.0.0.1:9200")
    //optionally you can define pool name as second argument
    registry.RegisterElastic("http://127.0.0.1:9200", "second_pool")
    // you can enable trace log
    registry.RegisterElasticWithTraceLog("http://127.0.0.1:9200", "second_pool")

    /* ClickHouse */
    registry.RegisterClickHouse("http://127.0.0.1:9000")
    //optionally you can define pool name as second argument
    registry.RegisterClickHouse("http://127.0.0.1:9000", "second_pool")
}

You can also create registry using yaml configuration file:
default:
    mysql: root:root@tcp(localhost:3310)/db
    mysqlEncoding: utf8 //optional, default is utf8mb4
    redis: localhost:6379:0
    streams:
      stream-1:
        - test-group-1
        - test-group-2
    elastic: http://127.0.0.1:9200
    elastic_trace: http://127.0.0.1:9201 //with trace log
    clickhouse: http://127.0.0.1:9000
    locker: default
    local_cache: 1000
second_pool:
    mysql: root:root@tcp(localhost:3311)/db2
      sentinel:
        master:1:
          - :26379
          - 192.156.23.11:26379
          - 192.156.23.12:26379
package main

import (
    "github.com/latolukasz/orm"
    "gopkg.in/yaml.v2"
    "io/ioutil"
)

func main() {

    yamlFileData, err := ioutil.ReadFile("./yaml")
    if err != nil {
        //...
    }
    
    var parsedYaml map[string]interface{}
    err = yaml.Unmarshal(yamlFileData, &parsedYaml)
    registry := InitByYaml(parsedYaml)
}

Defining entities

package main

import (
	"github.com/latolukasz/orm"
	"time"
)

func main() {

    type AddressSchema struct {
        Street   string
        Building uint16
    }
    
    type colors struct {
        Red    string
        Green  string
        Blue   string
        Yellow string
        Purple string
    }
    var Colors = &colors{
        orm.EnumModel,
    	Red:    "Red",
    	Green:  "Green",
    	Blue:   "Blue",
    	Yellow: "Yellow",
    	Purple: "Purple",
    }

    type testEntitySchema struct {
        orm.ORM
        ID                   uint
        Name                 string `orm:"length=100;index=FirstIndex"`
        NameNullable         string `orm:"length=100;index=FirstIndex"`
        BigName              string `orm:"length=max;required"`
        Uint8                uint8  `orm:"unique=SecondIndex:2,ThirdIndex"`
        Uint24               uint32 `orm:"mediumint=true"`
        Uint32               uint32
        Uint32Nullable       *uint32
        Uint64               uint64 `orm:"unique=SecondIndex"`
        Int8                 int8
        Int16                int16
        Int32                int32
        Int64                int64
        Rune                 rune
        Int                  int
        IntNullable          *int
        Bool                 bool
        BoolNullable         *bool
        Float32              float32
        Float64              float64
        Float64Nullable      *float64
        Float32Decimal       float32  `orm:"decimal=8,2"`
        Float64DecimalSigned float64  `orm:"decimal=8,2;unsigned=false"`
        Enum                 string   `orm:"enum=orm.colorEnum"`
        EnumNotNull          string   `orm:"enum=orm.colorEnum;required"`
        Set                  []string `orm:"set=orm.colorEnum"`
        YearNullable         *uint16   `orm:"year=true"`
        YearNotNull          uint16   `orm:"year=true"`
        Date                 *time.Time
        DateNotNull          time.Time
        DateTime             *time.Time `orm:"time=true"`
        DateTimeNotNull      time.Time  `orm:"time=true"`
        Address              AddressSchema
        Json                 interface{}
        ReferenceOne         *testEntitySchemaRef
        ReferenceOneCascade  *testEntitySchemaRef `orm:"cascade"`
        ReferenceMany        []*testEntitySchemaRef
        IgnoreField          []time.Time       `orm:"ignore"`
        Blob                 []byte
        MediumBlob           []byte `orm:"mediumblob=true"`
        LongBlob             []byte `orm:"longblob=true"`
        FieldAsJson          map[string]string
    }
    
    type testEntitySchemaRef struct {
        orm.ORM
        ID   uint
        Name string
    }
    type testEntitySecondPool struct {
    	orm.ORM `orm:"mysql=second_pool"`
    	ID                   uint
    }

    registry := &Registry{}
    var testEntitySchema testEntitySchema
    var testEntitySchemaRef testEntitySchemaRef
    var testEntitySecondPool testEntitySecondPool
    registry.RegisterEntity(testEntitySchema, testEntitySchemaRef, testEntitySecondPool)
    registry.RegisterEnumStruct("color", Colors)

    // now u can use:
    Colors.GetDefault() // "Red" (first field)
    Colors.GetFields() // ["Red", "Blue" ...]
    Colors.GetMapping() // map[string]string{"Red": "Red", "Blue": "Blue"}
    Colors.Has("Red") //true
    Colors.Has("Orange") //false
    
    //or register enum from slice
    registry.RegisterEnumSlice("color", []string{"Red", "Blue"})
    validatedRegistry.GetEnum("color").GetFields()
    validatedRegistry.GetEnum("color").Has("Red")
    
    //or register enum from map
    registry.RegisterEnumMap("color", map[string]string{"red": "Red", "blue": "Blue"}, "red")
}

There are only two golden rules you need to remember defining entity struct:

  • first field must be type of "ORM"
  • second argument must have name "ID" and must be type of one of uint, uint16, uint32, uint24, uint64, rune

By default entity is not cached in local cache or redis, to change that simply use key "redisCache" or "localCache" in "orm" tag for "ORM" field:

package main

import (
	"github.com/latolukasz/orm"
	"time"
)

func main() {

    type testEntityLocalCache struct {
    	orm.ORM `orm:"localCache"` //default pool
       //...
    }
   
   type testEntityLocalCacheSecondPool struct {
    	orm.ORM `orm:"localCache=second_pool"`
       //...
    }
   
   type testEntityRedisCache struct {
    	orm.ORM `orm:"redisCache"` //default pool
       //...
    }
   
   type testEntityRedisCacheSecondPool struct {
    	orm.ORM `orm:"redisCache=second_pool"`
       //...
    }

   type testEntityLocalAndRedisCache struct {
    	orm.ORM `orm:"localCache;redisCache"`
       //...
    }
}

Validated registry

Once you created your registry and registered all pools and entities you should validate it. You should also run it once when your application starts.

package main

import "github.com/latolukasz/orm"

func main() {
   registry := &Registry{}
   //register pools and entities
   validatedRegistry, err := registry.Validate()
}

Creating engine

You need to crete engine to start working with entities (searching, saving). You must create engine for each http request and thread.

package main

import "github.com/latolukasz/orm"

func main() {
   registry := &Registry{}
   //register pools and entities
   validatedRegistry, err := registry.Validate()
   engine := validatedRegistry.CreateEngine()
}

Checking and updating table schema

ORM provides useful object that describes entity structrure called TabelSchema:

package main

import "github.com/latolukasz/orm"

func main() {
   
   registry := &Registry{}
   // register
   validatedRegistry, err := registry.Validate() 
   engine := validatatedRegistry.CreateEngine()
   alters := engine.GetAlters()
   
   /*optionally you can execute alters for each model*/
   var userEntity UserEntity
   tableSchema := engine.GetRegistry().GetTableSchemaForEntity(userEntity)
   //or
   tableSchema := validatedRegistry.GetTableSchemaForEntity(userEntity)

   /*checking table structure*/
   tableSchema.UpdateSchema(engine) //it will create or alter table if needed
   tableSchema.DropTable(engine) //it will drop table if exist
   tableSchema.TruncateTable(engine)
   tableSchema.UpdateSchemaAndTruncateTable(engine)
   has, alters := tableSchema.GetSchemaChanges(engine)

   /*getting table structure*/
   db := tableSchema.GetMysql(engine)
   localCache, has := tableSchema.GetLocalCache(engine) 
   redisCache, has := tableSchema.GetRedisCache(engine)
   columns := tableSchema.GetColumns()
   tableSchema.GetTableName()
}

Adding, editing, deleting entities

package main

import "github.com/latolukasz/orm"

func main() {

     /* adding */

    entity := testEntity{Name: "Name 1"}
    engine.Flush(&entity)

    entity2 := testEntity{Name: "Name 1"}
    entity2.SetOnDuplicateKeyUpdate(orm.Bind{"Counter": 2}, entity2)
    engine.Flush(&entity2)

    entity2 = testEntity{Name: "Name 1"}
    engine.SetOnDuplicateKeyUpdate(orm.Bind{}, entity2) //it will change nothing un row
    engine.Flush(&entity)

    /*if you need to add more than one entity*/
    entity = testEntity{Name: "Name 2"}
    entity2 := testEntity{Name: "Name 3"}
    flusher := engine.NewFlusher()
    flusher.Track(&entity, &entity2)
    //it will execute only one query in MySQL adding two rows at once (atomic)
    flusher.Flush()
 
    /* editing */

    flusher := engine.NewFlusher().Track(&entity, &entity2)
    entity.Name = "New name 2"
    //you can also use (but it's slower):
    entity.SetField("Name", "New name 2")
    entity.IsDirty() //returns true
    entity2.IsDirty() //returns false
    flusher.Flush() //it will save data in DB for all dirty tracked entities
    engine.IsDirty(entity) //returns false
    
    /* deleting */
    entity2.Delete()
    //or
    flusher.Delete(&entity, &entity2).Flush()

    /* flush will panic if there is any error. You can catch 2 special errors using this method  */
    err := flusher.FlushWithCheck()
    //or
    err := flusher.FlushInTransactionWithCheck()
    orm.DuplicatedKeyError{} //when unique index is broken
    orm.ForeignKeyError{} //when foreign key is broken
    
    /* You can catch all errors using this method  */
    err := flusher.FlushWithFullCheck()
}

Transactions

package main

import "github.com/latolukasz/orm"

func main() {
	
    entity = testEntity{Name: "Name 2"}
    entity2 := testEntity{Name: "Name 3"}
    flusher := engine.NewFlusher().Track(&entity, &entity2)

    // DB transcation
    flusher.FlushInTransaction()
    // or redis lock
    flusher.FlushWithLock("default", "lock_name", 10 * time.Second, 10 * time.Second)
    // or DB transcation nad redis lock
    flusher.FlushInTransactionWithLock("default", "lock_name", 10 * time.Second, 10 * time.Second)
 
    //manual transaction
    db := engine.GetMysql()
    db.Begin()
    defer db.Rollback()
    //run queries
    db.Commit()

Loading entities using primary key

package main

import "github.com/latolukasz/orm"

func main() {

    var entity testEntity
    has := engine.LoadByID(1, &entity)

    var entities []*testEntity
    missing := engine.LoadByIDs([]uint64{1, 3, 4}, &entities) //missing contains IDs that are missing in database

}

package main

import "github.com/latolukasz/orm"

func main() {

    var entities []*testEntity
    pager := orm.NewPager(1, 1000)
    where := orm.NewWhere("`ID` > ? AND `ID` < ?", 1, 8)
    engine.Search(where, pager, &entities)
    
    //or if you need number of total rows
    totalRows := engine.SearchWithCount(where, pager, &entities)
    
    //or if you need only one row
    where := onm.NewWhere("`Name` = ?", "Hello")
    var entity testEntity
    found := engine.SearchOne(where, &entity)
    
    //or if you need only primary keys
    ids := engine.SearchIDs(where, pager, entity)
    
    //or if you need only primary keys and total rows
    ids, totalRows = engine.SearchIDsWithCount(where, pager, entity)
}

Reference one to one

package main

import "github.com/latolukasz/orm"

func main() {

    type UserEntity struct {
        ORM
        ID                   uint64
        Name                 string
        School               *SchoolEntity `orm:"required"` // key is "on delete restrict" by default not not nullable
        SecondarySchool      *SchoolEntity // key is nullable
    }
    
    type SchoolEntity struct {
        ORM
        ID                   uint64
        Name                 string
    }

    type UserHouse struct {
        ORM
        ID                   uint64
        User                 *UserEntity  `orm:"cascade;required"` // on delete cascade and is not nullable
    }
    
    // saving in DB:

    user := UserEntity{Name: "John"}
    school := SchoolEntity{Name: "Name of school"}
    house := UserHouse{Name: "Name of school"}
    engine.Track(&user, &school, &house)
    user.School = school
    house.User = user
    engine.Flush()

    // loading references: 

    _ = engine.LoadById(1, &user)
    user.School != nil //returns true, School has ID: 1 but other fields are nof filled
    user.School.ID == 1 //true
    user.School.Loaded() //false
    user.Name == "" //true
    user.School.Load(engine) //it will load school from db
    user.School.Loaded() //now it's true, you can access school fields like user.School.Name
    user.Name == "Name of school" //true
    
    //If you want to set reference and you have only ID:
    user.School = &SchoolEntity{ID: 1}

    // detaching reference
    user.School = nil

    // preloading references
    engine.LoadByID(1, &user, "*") //all references
    engine.LoadByID(1, &user, "School") //only School
    engine.LoadByID(1, &user, "School", "SecondarySchool") //only School and SecondarySchool
    engine.LoadByID(1, &userHouse, "User/School", "User/SecondarySchool") //User, School and SecondarySchool in each User
    engine.LoadByID(1, &userHouse, "User/*") // User, all references in User
    engine.LoadByID(1, &userHouse, "User/*/*") // User, all references in User and all references in User subreferences
    //You can have as many levels you want: User/School/AnotherReference/EvenMore/
    
    //You can preload referenes in all search and load methods:
    engine.LoadByIDs()
    engine.Search()
    engine.SearchOne()
    engine.CachedSearch()
    ...
}

Cached queries

package main

import "github.com/latolukasz/orm"

func main() {

    //Fields that needs to be tracked for changes should start with ":"

    type UserEntity struct {
        ORM
        ID                   uint64
        Name                 string
        Age                  uint16
        IndexAge             *CachedQuery `query:":Age = ? ORDER BY :ID"`
        IndexAll             *CachedQuery `query:""` //cache all rows
        IndexName            *CachedQuery `queryOne:":Name = ?"`
    }

    pager := orm.NewPager(1, 1000)
    var users []*UserEntity
    var user  UserEntity
    totalRows := engine.CachedSearch(&users, "IndexAge", pager, 18)
    totalRows = engine.CachedSearch(&users, "IndexAll", pager)
    has := engine.CachedSearchOne(&user, "IndexName", "John")

}

Lazy flush

Sometimes you want to flush changes in database, but it's ok if data is flushed after some time. For example when you want to save some logs in database.

package main

import "github.com/latolukasz/orm"

func main() {
    
    // you need to register redis  
    registry.RegisterRedis("localhost:6379", 0)
    registry.RegisterRedis("localhost:6380", 0, "another_redis")
    
    // .. create engine

    type User struct {
       ORM  `orm:"log"`
       ID   uint
       Name string
       Age  int `orm:"skip-log"` //Don't track this field
    }
   
    // optionally you can set optional redis pool used to queue all events
    type Dog struct {
       ORM  `orm:"asyncRedisLazyFlush=another_redis"`
       ID   uint
       Name string
    }
       
    // now in code you can use FlushLazy() methods instead of Flush().
    // it will send changes to queue (database and cached is not updated yet)
    engine.FlushLazy()
    
    // you need to run code that will read data from queue and execute changes
    // run in separate goroutine (cron script)
    consumer := NewAsyncConsumer(engine, "my-consumer", 1) // you can run maximum one consumer
    consumer.Digest() //It will wait for new messages in a loop, run receiver.DisableLoop() to run loop once

    consumerAnotherPool := NewAsyncConsumer(engine,  "my-consumer", 5) // you can run up to 5 consumers at the same time
    consumerAnotherPool.Digets()
}

Request cache

It's a good practice to cache entities in one short request (e.g. http request) to reduce number of requests to databases.

If you are using more than one goroutine (for example in GraphQL backend implementation) you can enable Data loader in engine to group many queries into one and reduce number of queries. You can read more about idea behind it here.

package main

import "github.com/latolukasz/orm"

func main() {
    engine.EnableDataLoader(true)
}

Otherwise set false and all entities will be cached in a simple temporary cache:

package main

import "github.com/latolukasz/orm"

func main() {
    engine.EnableDataLoader(false) 
}

Log entity changes

ORM can store in database every change of entity in special log table.

package main

import "github.com/latolukasz/orm"

func main() {

    //it's recommended to keep logs in separated DB
    registry.RegisterMySQLPool("root:root@tcp(localhost:3306)/log_database", "log_db_pool")
    // you need to register default Redis   
    registry.RegisterRedis("localhost:6379", 0)
    registry.RegisterRedis("localhost:6380", 0, "another_redis")

    //next you need to define in Entity that you want to log changes. Just add "log" tag or define mysql pool name
    type User struct {
        ORM  `orm:"log"`
        ID   uint
        Name string
        Age  int `orm:"skip-log"` //Don't track this field
    }
    
    // optionally you can set optional redis pool used to queue all events
     type Dog struct {
        ORM  `orm:"log=log_db_pool;asyncRedisLogs=another_redis"`
        ID   uint
        Name string
     }

    // Now every change of User will be saved in log table
    
    // You can add extra data to log, simply use this methods before Flush():
    engine.SetLogMetaData("logged_user_id", 12) 
    engine.SetLogMetaData("ip", request.GetUserIP())
    // you can set meta only in specific entity
    engine.SetEntityLogMeta("user_name", "john", entity)
    
    consumer := NewAsyncConsumer(engine, "my-consumer",  1)
    consumer.Digets() //it will wait for new messages in queue

    consumerAnotherPool := NewAsyncConsumer(engine, "my-consumer", 1)
    consumerAnotherPool.Digets()
}

Dirty stream

You can send event to event broker if any specific data in entity was changed.

package main

import "github.com/latolukasz/orm"

func main() {

	//define at least one redis pool
    registry.RegisterRedis("localhost:6379", 0, "event-broker-pool")
    //define stream with consumer groups for events
    registry.RegisterRedisStream("user_changed", "event-broker-pool", []string{"my-consumer-group"})
    registry.RegisterRedisStream("age_name_changed", "event-broker-pool", []string{"my-consumer-group"})
    registry.RegisterRedisStream("age_changed", "event-broker-pool", []string{"my-consumer-group"})

    // create engine
    
    // next you need to define in Entity that you want to log changes. Just add "dirty" tag
    type User struct {
        orm.ORM  `orm:"dirty=user_changed"` //define dirty here to track all changes
        ID       uint
        Name     string `orm:"dirty=age_name_changed"` //event will be send to age_name_changed if Name or Age changed
        Age      int `orm:"dirty=age_name_changed,age_changed"` //event will be send to age_changed if Age changed
    }
 
    consumer := engine.GetEventBroker().Consume("my-consumer", "my-consumer-group", 1)

    consumer.Consume(context.Background(), 100, func(events []orm.Event) {
        for _, event := range events {
           dirty := orm.EventDirtyEntity(event) // created wrapper around event to easily access data
           if dirty.Added() {
           	 fmt.Printf("Entity %s with ID %d was added", dirty.TableSchema().GetType().String(), dirty.ID())
           } else if dirty.Updated() {
           	 fmt.Printf("Entity %s with ID %d was updated", dirty.TableSchema().GetType().String(), dirty.ID())
           } else if dirty.Deleted() {
             fmt.Printf("Entity %s with ID %d was deleted", dirty.TableSchema().GetType().String(), dirty.ID())
           }
           event.Ack()
        }
    })
}


Fake delete

If you want to keep deleted entity in database but ny default this entity should be excluded from all engine.Search() and engine.CacheSearch() queries you can use FakeDelete column. Simply create field bool with name "FakeDelete".

func main() {

    type UserEntity struct {
        ORM
        ID                   uint64
        Name                 string
        FakeDelete           bool
    }

    //you can delete in two ways:
    engine.Delete(user) -> will set user.FakeDelete = true
    //or:
    user.FakeDelete = true

    engine.Flush(user) //it will save entity id in Column `FakeDelete`.

    //will return all rows where `FakeDelete` = 0
    total, err = engine.SearchWithCount(NewWhere("1"), nil, &rows)

    //To force delete (remove row from DB):
    engine.ForceDelete(user)
}


Working with Redis

package main

import "github.com/latolukasz/orm"

func main() {

    config.RegisterRedis("localhost:6379", 0)
    
    //storing data in cached for x seconds
    val := engine.GetRedis().GetSet("key", 1, func() interface{} {
		return "hello"
	})
    
    //standard redis api
    keys := engine.GetRedis().LRange("key", 1, 2)
    engine.GetRedis().LPush("key", "a", "b")
    //...

    //rete limiter
    valid := engine.GetRedis().RateLimit("resource_name", redis_rate.PerMinute(10))
}

Working with local cache

package main

import "github.com/latolukasz/orm"

func main() {
    
    registry.RegisterLocalCache(1000)
    
    //storing data in cached for x seconds
    val := engine.GetLocalCache().GetSet("key", 1, func() interface{} {
        return "hello"
    })
    
    //getting value
    value, has := engine.GetLocalCache().Get("key")
    
    //getting many values
    values := engine.GetLocalCache().MGet("key1", "key2")
    
    //setting value
    engine.GetLocalCache().Set("key", "value")
    
    //setting values
    engine.GetLocalCache().MSet("key1", "value1", "key2", "value2" /*...*/)
    
    //getting values from hash set (like redis HMGET)
    values = engine.GetLocalCache().HMget("key")
    
    //setting values in hash set
    engine.GetLocalCache().HMset("key", map[string]interface{}{"key1" : "value1", "key2": "value 2"})

    //deleting value
    engine.GetLocalCache().Remove("key1", "key2" /*...*/)
    
    //clearing cache
    engine.GetLocalCache().Clear()

}

Working with mysql

package main

import (
    "database/sql"
    "github.com/latolukasz/orm"
)

func main() {
    
    // register mysql pool
    registry.RegisterMySQLPool("root:root@tcp(localhost:3306)/database_name")

    res := engine.GetMysql().Exec("UPDATE `table_name` SET `Name` = ? WHERE `ID` = ?", "Hello", 2)

    var row string
    found := engine.GetMysql().QueryRow(orm.NewWhere("SELECT * FROM `table_name` WHERE  `ID` = ?", 1), &row)
    
    results, def := engine.GetMysql().Query("SELECT * FROM `table_name` WHERE  `ID` > ? LIMIT 100", 1)
    defer def()
    for results.Next() {
    	var row string
        results.Scan(&row)
    }
    def() //if it's not last line in this method
}

package main

import (
    "github.com/latolukasz/orm"
)

func main() {

    type TestIndex struct {
    }
    
    func (i *TestIndex) GetName() string {
    	return "test_index"
    }
    
    func (i *TestIndex) GetDefinition() map[string]interface{} {
        return map[string]interface{}{
            "settings": map[string]interface{}{
                "number_of_replicas": "1",
                "number_of_shards":   "1",
            },
            "mappings": map[string]interface{}{
                "properties": map[string]interface{}{
                    "Name": map[string]interface{}{
                        "type":       "keyword",
                        "normalizer": "case_insensitive",
                    },
                },
            },
        }
    }

    
    // register elastic search pool and index
    registry.RegisterElastic("http://127.0.0.1:9200")
    registry.RegisterElasticIndex(&TestIndex{})


    e := engine.GetElastic()

    // create indices
	for _, alter := range engine.GetElasticIndexAlters() {
        // alter.Safe is true if index does not exists or is not empty
		engine.GetElastic(alter.Pool).CreateIndex(alter.Index)
	}

    query := elastic.NewBoolQuery()
	query.Must(elastic.NewTermQuery("user_id", 12))
    options := &orm.SearchOptions{}
    options.AddSort("created_at", true).AddSort("name", false)
	results := e.Search("users", query, orm.NewPager(1, 10), options)
}

Working with ClickHouse

package main

import (
    "github.com/latolukasz/orm"
)

func main() {
    
    // register elastic search pool
    registry.RegisterClickHouse("http://127.0.0.1:9000")

    ch := engine.GetClickHouse()

    ch.Exec("INSERT INTO `table` (name) VALUES (?)", "hello")

    statement, def := ch.Prepare("INSERT INTO `table` (name) VALUES (?)")
    defer def()
    statement.Exec("hello")
    statement.Exec("hello 2")

    rows, def := ch.Queryx("SELECT FROM `table` WHERE x = ? AND y = ?", 1, "john")
    defer def()
    for rows.Next() {
    	m := &MyStruct{}
        err := rows.StructScan(m)
    }

    ch.Begin()
    defer ch.Rollback()
    // run queries
    defer ch.Commit()
}

Working with Locker

Shared cached that is using redis

package main

import "github.com/latolukasz/orm"

func main() {

    // register redis and locker
    registry.RegisterRedis("localhost:6379", 0, "my_pool")
    registry.RegisterLocker("default", "my_pool")
    
    locker, _ := engine.GetLocker()
    lock := locker.Obtain("my_lock", 5 * Time.Second, 1 * Time.Second)

    defer lock.Release()
    
    // do smth
    
    ttl := lock.TTL()
    if ttl == 0 {
        panic("lock lost")
    }
}

Query logging

You can log all queries:

  • queries to MySQL database (insert, select, update)
  • requests to Redis
  • requests to Elastic Search
  • queries to CickHouse
package main

import "github.com/latolukasz/orm"

func main() {
	
    //enable human friendly console log
    engine.EnableQueryDebug() //MySQL, redis, Elastic Search, ClickHouse queries (local cache in excluded bt default)
    engine.EnableQueryDebug(orm.QueryLoggerSourceRedis, orm.QueryLoggerSourceLocalCache)

    //adding custom logger example:
    engine.AddQueryLogger(json.New(os.Stdout), log.LevelWarn) //MySQL, redis warnings and above
    engine.AddQueryLogger(es.New(os.Stdout), log.LevelError, orm.QueryLoggerSourceRedis)
}    

Logger

package main

import "github.com/latolukasz/orm"

func main() {
	
    //enable json logger with proper level
    engine.EnableLogger(log.InfoLevel)
    //or enable human friendly console logger
    engine.EnableDebug()
    
    //you can add special fields to all logs
    engine.Log().AddFields(log.Fields{"user_id": 12, "session_id": "skfjhfhhs1221"})

    //printing logs
    engine.Log().Warn("message", nil)
    engine.Log().Debug("message", log.Fields{"user_id": 12})
    engine.Log().Error(err, nil)
    engine.Log().ErrorMessage("ups, that is strange", nil)


    //handling recovery
    if err := recover(); err != nil {
    	engine.Log().Error(err, nil)
    }

    //filling log with data from http.Request
    engine.Log().AddFieldsFromHTTPRequest(request, "197.21.34.22")

}    

Event broker

ORM provides easy way to use event broker.

First yuo need to define streams and consumer groups:

#YAML config file
default:
  redis: localhost:6381:0 // redis is required
  streams:
    stream-1:
      - test-group-1
      - test-group-2
    stream-2:
      - test-group-1
    stream-3:
      - test-group-3

or using go:

package main

import "github.com/latolukasz/orm"

func main() {
 registry := &orm.Registry{}
 registry.RegisterRedisStream("stream-1", "default", []string{"test-group-1", "test-group-2"})
 registry.RegisterRedisStream("stream-2", "default", []string{"test-group-1"})
 registry.RegisterRedisStream("stream-3", "default", []string{"test-group-3"})
}    

Publishing and receiving events :

package main

import (
 "context"
 "github.com/latolukasz/orm"
)

func main() {

 // .. create engine

 type Person struct {
  Name string
  Age  int
 }

 // fastest, no serialization
 engine.GetEventBroker().PublishMap("stream-1", orm.EventAsMap{"key": "value", "anotherKey": "value 2"})
 
 // using serialization
 engine.GetEventBroker().Publish("stream-3", Person{Name: "Adam", Age: 18})

 // publishing many at once, recommended because it's much faster than one by one
 flusher :=  engine.GetEventBroker().NewFlusher()
 flusher.PublishMap("stream-1", orm.EventAsMap{"key": "value", "anotherKey": "value 2"})
 flusher.Publish("stream-1", Person{Name: "Adam", Age: 18})
 flusher.Flush()
 
 // reading from "stream-1" and "stream-2" streams, you can run max one consumer at once
 consumerTestGroup1 := engine.GetEventBroker().Consumer("my-consumer", "test-group-1", 1)
 
 // reading max 100 events in one loop, this line stop execution, waiting for new events
 consumerTestGroup1.Consumer(context.Background(), 100, func(events []orm.Event) {
 	for _, event := range events {
            values := event.RawData() // map[string]interface{}{"key": "value", "anotherKey": "value 2"}
            //do some work
            event.Ack() // this line is acknowledging event
 	}
 })

 // auto acknowledging
 consumerTestGroup1.Consumer(context.Background(), 100, func(events []orm.Event) { 
 	//do some work, for example put all events at once to DB
 	// in this example all events will be acknowledge when this method is finished 
 })

 // skipping some events
 consumerTestGroup1.Consumer(context.Background(), 100, func(events []orm.Event) {
  for _, event := range events {
        if someCondition {
             event.Ack()
        } else {
             event.Skip() //this event will be consumed again later
        }
    }
 })

 // reading from "stream-3" stream, you can run max to two consumers at once
 consumerTestGroup3 := engine.GetEventBroker().Consumer("my-consumer", "test-group-2", 2)
 consumerTestGroup3.DisableLoop() // all events will be consumed once withour waiting for new events   

 consumerTestGroup3.Consumer(context.Background(), 100, func(events []orm.Event) {
    var person Person
 	for _, event := range events {
        err := event.Unserialize(&person)
        if err != nil {
        	// ...
        }
        //do some work
        event.Ack() // this line is acknowledging event
    }
 })

}    

You can register special function that will handle panics:

 consumer := broker.Consumer("test-consumer", "test-group")
 consumer.SetErrorHandler(func(err interface{}, event Event) error {
   // log error somewhere
   // optionally you can remove this event from stream
   event.Ack()
   return nil // do not panic, error is handled above, you can return err if you want consumer to stop with panic
 })

Setting another redis pool for AsyncConsumer:

another_pool:
  redis: localhost:6381:0
  streams:
   orm-lazy-channel: # FlushLazy()
      - default-group # group name for AsyncConsumer
    orm-log-channel: # adding changes to logs
      - default-group # group name for AsyncConsumer
      - test-group-2 # you can register another consumers to read logs  

Be sure your redis has Redis Search module 2.X installed.

Indexer

You need to run special script that is indexing data in redis search for you. Be sure that this script is running in your code:

package main

import "github.com/latolukasz/orm"
func main() {
 indexer := orm.NewRedisSearchIndexer(engine)
 indexer.Run(context.Background())
}
Redis search index alters

Every time you run your code be sure you are checking if redis search indices are valid:

altersSearch := engine.GetRedisSearchIndexAlters()
for _, alter := range altersSearch {
	// show them or execute: 
	alter.Execute()
}

It's very easy to search ofr entities. Simply use special orm entity tag close to fields that should be used in search:

package main

import "github.com/latolukasz/orm"

type MyEntity struct {
 orm.ORM             `orm:"redisSearch=search"`
 ID              uint
 Name            string             `orm:"searchable"`
 Age             uint64             `orm:"searchable;sortable"`
 Balance         int64              `orm:"sortable"`
 Weight          float64            `orm:"searchable"`
 Enum            string             `orm:"enum=orm.TestEnum;required;searchable"`
}
  

That's it:) All you need to do from now is to add/edit/delete entities as always using Flush() and FlushLazy().

Tags:

  • searchable - you can search for this entity using where condition for this field
  • sortable - you can sort results using this field

Now it's time to search some entities:

package main

import "github.com/latolukasz/orm"

func main() {

  // engine := ...	 
  	
 query := &orm.RedisSearchQuery{}
 query.Query("adam").Sort("Age", false).FilterIntMinMax("Age", 6, 8).FilterTag("Enum", "active", "blocked")
 
 // getting ids
 ids, total := engine.RedisSearchIds(entity, query, orm.NewPager(1, 50))
 // getting entities
 total = engine.RedisSearch(&entities, query, NewPager(1, 10))
 // getting entity
 found := engine.RedisSearchOne(entity, query)
 
 // some another examples of query
 query.FilterInt("Age", 12)
 query.FilterIntNull("Age")
 query.FilterIntGreaterEqual("Age", 12)
 query.FilterDateGreaterEqual("Age", time.Now())
 query.FilterBool("Active", true)
 query.Query("@y:foo (-@x:foo) (-@x:bar)")
}    

Read more about redis search query syntax here.

Building your own redis search index

If you need to build more advanced redis search simply register an index manually. Below example:

package main

import "github.com/latolukasz/orm/tools"

func main() {
  registry := &orm.Registry{}
  registry.RegisterRedis("localhost:6383", 0, "search")
  
  // register an index:
  myIndex := &orm.RedisSearchIndex{}
  myIndex.Name = "my-index"
  myIndex.RedisPool = "search"
  myIndex.Prefixes = []string{"my-index:"}
  myIndex.AddTextField("name", 1, true, false, false)
  myIndex.AddNumericField("age", true, false)
  myIndex.AddGeoField("location", false, false)
  myIndex.Indexer = func(engine *orm.Engine, lastID uint64, pusher orm.RedisSearchIndexPusher) (newID uint64, hasMore bool) {
     rows := // select from database WHERE ID > lastID ORDER BY ID LIMIT 1000
     for _, row := range rows {
      pusher.NewDocument("my-index:" + row.ID)
      pusher.SetField("name", row.Name)
      pusher.SetField("age", row.Age)
      pusher.SetField("location", row.location)
      pusher.PushDocument()
      lastID = row.id
     }
     return lastID, len(rows) < 1000 // return last used id and false if there ar eno more rows ro index
  }
  registry.RegisterRedisSearchIndex(myIndex)
  validatedRegistry, _ := registry.Validate()
  engine := validatedRegistry.CreateEngine()
  
  // adding, updating documents:
  pusher := engine.NewRedisSearchIndexPusher("search")
  pusher.NewDocument("my-index:33")
  pusher.SetField("name", "Tom")
  pusher.SetField("age", 12)
  pusher.SetField("location", "52.2982648,17.0103596")
  pusher.PushDocument()
  pusher.NewDocument("my-index:34")
  pusher.SetField("name", "Adam")
  pusher.SetField("age", 18)
  pusher.PushDocument()
  pusher.DeletewDocuments("my-index:35", "my-index:36")
  pusher.Flush()
 
  // searching
  search := engine.GetRedisSearch("search")
  query := &orm.RedisSearchQuery{}
  query.Query("tom").Verbatim().NoStopWords().Sort("age", true)
  
  // return data from index
  total, rowsRaw := search.Search("my-index", query, orm.NewPager(1, 2))
  // return just keys
  total, keys := search.SearchKeys("my-index", query, orm.NewPager(1, 2))
  
  // return only name and age
 query.Return("name", "age")
 total, rowsRaw := search.Search("my-index", query, orm.NewPager(1, 2))
}    

Tools

package main

import "github.com/latolukasz/orm/tools"

func main() {
   // Redis streams statistics	
   tools.GetRedisStreamsStatistics(engine)
   // Redis statistics	
   tools.GetRedisStatistics(engine)
   // Redis search statistics	
   tools.GetRedisSearchStatistics(engine)
}    

Health check

ORM provides special method that can be used to check that all database services are up and running.

package main

import (
 "fmt"
 "github.com/latolukasz/orm/tools"
)

func main() {
 registry := &orm.Registry{}
 registry.RegisterRedis("localhost:6383")
 // register other services
 validatedRegistry, _ := registry.Validate()
 engine := validatedRegistry.CreateEngine()

 errors, warnings, valid := engine.HealthCheck()
 for _, err := range errors {
    fmt.Printf("Error for step %s (%s): %s\n", err.Name, err.Description, err.Message)
 }
 for _, warn := range warnings {
    fmt.Printf("Warning for step %s (%s): %s\n", warn.Name, warn.Description, warn.Message)
 }
 for _, step := range valid {
    fmt.Printf("Warning for step %s (%s) passed\n", step.Name, step.Description)
 }

}    

Documentation

Index

Constants

View Source
const (
	QueryLoggerSourceDB = iota
	QueryLoggerSourceRedis
	QueryLoggerSourceElastic
	QueryLoggerSourceClickHouse
	QueryLoggerSourceLocalCache
	QueryLoggerSourceStreams
)

Variables

This section is empty.

Functions

func EscapeRedisSearchString

func EscapeRedisSearchString(val string) string

Types

type Alter

type Alter struct {
	SQL  string
	Safe bool
	Pool string
}

type AsyncConsumer

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

func NewAsyncConsumer

func NewAsyncConsumer(engine *Engine, name string) *AsyncConsumer

func (*AsyncConsumer) Digest

func (r *AsyncConsumer) Digest(ctx context.Context, count int)

func (*AsyncConsumer) DisableLoop

func (r *AsyncConsumer) DisableLoop()

func (*AsyncConsumer) SetErrorHandler

func (r *AsyncConsumer) SetErrorHandler(handler ConsumerErrorHandler)

func (*AsyncConsumer) SetHeartBeat

func (r *AsyncConsumer) SetHeartBeat(duration time.Duration, beat func())

func (*AsyncConsumer) SetLogLogger

func (r *AsyncConsumer) SetLogLogger(logger func(log *LogQueueValue))

type Bind

type Bind map[string]interface{}

type CachedQuery

type CachedQuery struct{}

type ClickHouse

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

func (*ClickHouse) Begin

func (c *ClickHouse) Begin()

func (*ClickHouse) Commit

func (c *ClickHouse) Commit()

func (*ClickHouse) Exec

func (c *ClickHouse) Exec(query string, args ...interface{}) sql.Result

func (*ClickHouse) Prepare

func (c *ClickHouse) Prepare(query string) (preparedStatement *PreparedStatement, deferF func())

func (*ClickHouse) Queryx

func (c *ClickHouse) Queryx(query string, args ...interface{}) (rows *sqlx.Rows, deferF func())

func (*ClickHouse) Rollback

func (c *ClickHouse) Rollback()

type ClickHouseConfig

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

type ConsumerErrorHandler

type ConsumerErrorHandler func(err interface{}, event Event) error

type DB

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

func (*DB) Begin

func (db *DB) Begin()

func (*DB) Commit

func (db *DB) Commit()

func (*DB) Exec

func (db *DB) Exec(query string, args ...interface{}) ExecResult

func (*DB) GetDatabaseName

func (db *DB) GetDatabaseName() string

func (*DB) GetPoolCode

func (db *DB) GetPoolCode() string

func (*DB) Query

func (db *DB) Query(query string, args ...interface{}) (rows Rows, deferF func())

func (*DB) QueryRow

func (db *DB) QueryRow(query *Where, toFill ...interface{}) (found bool)

func (*DB) Rollback

func (db *DB) Rollback()

type DBConfig

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

type DirtyEntityEvent

type DirtyEntityEvent interface {
	ID() uint64
	TableSchema() TableSchema
	Added() bool
	Updated() bool
	Deleted() bool
}

func EventDirtyEntity

func EventDirtyEntity(e Event) DirtyEntityEvent

type DuplicatedKeyError

type DuplicatedKeyError struct {
	Message string
	Index   string
}

func (*DuplicatedKeyError) Error

func (err *DuplicatedKeyError) Error() string

type Elastic

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

func (*Elastic) Client

func (e *Elastic) Client() *elastic.Client

func (*Elastic) CreateIndex

func (e *Elastic) CreateIndex(index ElasticIndexDefinition)

func (*Elastic) DropIndex

func (e *Elastic) DropIndex(index ElasticIndexDefinition)

func (*Elastic) Search

func (e *Elastic) Search(index string, query elastic.Query, pager *Pager, options *SearchOptions) *elastic.SearchResult

type ElasticConfig

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

type ElasticIndexAlter

type ElasticIndexAlter struct {
	Index       ElasticIndexDefinition
	Safe        bool
	Pool        string
	NewMapping  map[string]interface{}
	OldMapping  map[string]interface{}
	NewSettings interface{}
	OldSettings interface{}
}

type ElasticIndexDefinition

type ElasticIndexDefinition interface {
	GetName() string
	GetDefinition() map[string]interface{}
}

type Engine

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

func (*Engine) AddQueryLogger

func (e *Engine) AddQueryLogger(handler logApex.Handler, level logApex.Level, source ...QueryLoggerSource)

func (*Engine) CachedSearch

func (e *Engine) CachedSearch(entities interface{}, indexName string, pager *Pager, arguments ...interface{}) (totalRows int)

func (*Engine) CachedSearchCount

func (e *Engine) CachedSearchCount(entity Entity, indexName string, arguments ...interface{}) int

func (*Engine) CachedSearchIDs

func (e *Engine) CachedSearchIDs(entity Entity, indexName string, pager *Pager, arguments ...interface{}) (totalRows int, ids []uint64)

func (*Engine) CachedSearchLazy

func (e *Engine) CachedSearchLazy(entities interface{}, indexName string, pager *Pager, arguments ...interface{}) (totalRows int)

func (*Engine) CachedSearchOne

func (e *Engine) CachedSearchOne(entity Entity, indexName string, arguments ...interface{}) (found bool)

func (*Engine) CachedSearchOneLazy

func (e *Engine) CachedSearchOneLazy(entity Entity, indexName string, arguments ...interface{}) (found bool)

func (*Engine) CachedSearchOneWithReferences

func (e *Engine) CachedSearchOneWithReferences(entity Entity, indexName string, arguments []interface{}, references []string) (found bool)

func (*Engine) CachedSearchOneWithReferencesLazy

func (e *Engine) CachedSearchOneWithReferencesLazy(entity Entity, indexName string, arguments []interface{}, references []string) (found bool)

func (*Engine) CachedSearchWithReferences

func (e *Engine) CachedSearchWithReferences(entities interface{}, indexName string, pager *Pager,
	arguments []interface{}, references []string) (totalRows int)

func (*Engine) CachedSearchWithReferencesLazy

func (e *Engine) CachedSearchWithReferencesLazy(entities interface{}, indexName string, pager *Pager,
	arguments []interface{}, references []string) (totalRows int)

func (*Engine) ClearByIDs

func (e *Engine) ClearByIDs(entity Entity, ids ...uint64)

func (*Engine) Delete

func (e *Engine) Delete(entity Entity)

func (*Engine) DeleteMany

func (e *Engine) DeleteMany(entities ...Entity)

func (*Engine) EnableDebug

func (e *Engine) EnableDebug()

func (*Engine) EnableLogger

func (e *Engine) EnableLogger(level logApex.Level, handlers ...logApex.Handler)

func (*Engine) EnableQueryDebug

func (e *Engine) EnableQueryDebug(source ...QueryLoggerSource)

func (*Engine) EnableRequestCache

func (e *Engine) EnableRequestCache(goroutines bool)

func (*Engine) Flush

func (e *Engine) Flush(entity Entity)

func (*Engine) FlushLazy

func (e *Engine) FlushLazy(entity Entity)

func (*Engine) FlushLazyMany

func (e *Engine) FlushLazyMany(entities ...Entity)

func (*Engine) FlushMany

func (e *Engine) FlushMany(entities ...Entity)

func (*Engine) FlushWithCheck

func (e *Engine) FlushWithCheck(entity Entity) error

func (*Engine) FlushWithCheckMany

func (e *Engine) FlushWithCheckMany(entities ...Entity) error

func (*Engine) ForceDelete

func (e *Engine) ForceDelete(entity Entity)

func (*Engine) GetAlters

func (e *Engine) GetAlters() (alters []Alter)

func (*Engine) GetClickHouse

func (e *Engine) GetClickHouse(code ...string) *ClickHouse

func (*Engine) GetElastic

func (e *Engine) GetElastic(code ...string) *Elastic

func (*Engine) GetElasticIndexAlters

func (e *Engine) GetElasticIndexAlters() (alters []ElasticIndexAlter)

func (*Engine) GetEventBroker

func (e *Engine) GetEventBroker() EventBroker

func (*Engine) GetLocalCache

func (e *Engine) GetLocalCache(code ...string) *LocalCache

func (*Engine) GetLocker

func (e *Engine) GetLocker(code ...string) *Locker

func (*Engine) GetMysql

func (e *Engine) GetMysql(code ...string) *DB

func (*Engine) GetRedis

func (e *Engine) GetRedis(code ...string) *RedisCache

func (*Engine) GetRedisSearch

func (e *Engine) GetRedisSearch(code ...string) *RedisSearch

func (*Engine) GetRedisSearchIndexAlters

func (e *Engine) GetRedisSearchIndexAlters() (alters []RedisSearchIndexAlter)

func (*Engine) GetRegistry

func (e *Engine) GetRegistry() ValidatedRegistry

func (*Engine) HealthCheck

func (e *Engine) HealthCheck() (errors []HealthCheckError, warnings []HealthCheckError, valid []HealthCheckStep)

func (*Engine) Load

func (e *Engine) Load(entity Entity, references ...string)

func (*Engine) LoadByID

func (e *Engine) LoadByID(id uint64, entity Entity, references ...string) (found bool)

func (*Engine) LoadByIDLazy

func (e *Engine) LoadByIDLazy(id uint64, entity Entity, references ...string) (found bool)

func (*Engine) LoadByIDs

func (e *Engine) LoadByIDs(ids []uint64, entities interface{}, references ...string) (missing []uint64)

func (*Engine) LoadByIDsLazy

func (e *Engine) LoadByIDsLazy(ids []uint64, entities interface{}, references ...string) (missing []uint64)

func (*Engine) LoadLazy

func (e *Engine) LoadLazy(entity Entity, references ...string)

func (*Engine) Log

func (e *Engine) Log() Log

func (*Engine) NewFlusher

func (e *Engine) NewFlusher() Flusher

func (*Engine) NewRedisFlusher

func (e *Engine) NewRedisFlusher() RedisFlusher

func (*Engine) NewRedisSearchIndexPusher

func (e *Engine) NewRedisSearchIndexPusher(pool string) RedisSearchIndexPusher

func (*Engine) RedisSearch

func (e *Engine) RedisSearch(entities interface{}, query *RedisSearchQuery, pager *Pager, references ...string) (totalRows uint64)

func (*Engine) RedisSearchIds

func (e *Engine) RedisSearchIds(entity Entity, query *RedisSearchQuery, pager *Pager) (ids []uint64, totalRows uint64)

func (*Engine) RedisSearchLazy

func (e *Engine) RedisSearchLazy(entities interface{}, query *RedisSearchQuery, pager *Pager, references ...string) (totalRows uint64)

func (*Engine) RedisSearchOne

func (e *Engine) RedisSearchOne(entity Entity, query *RedisSearchQuery, references ...string) (found bool)

func (*Engine) RedisSearchOneLazy

func (e *Engine) RedisSearchOneLazy(entity Entity, query *RedisSearchQuery, references ...string) (found bool)

func (*Engine) Search

func (e *Engine) Search(where *Where, pager *Pager, entities interface{}, references ...string)

func (*Engine) SearchIDs

func (e *Engine) SearchIDs(where *Where, pager *Pager, entity Entity) []uint64

func (*Engine) SearchIDsWithCount

func (e *Engine) SearchIDsWithCount(where *Where, pager *Pager, entity Entity) (results []uint64, totalRows int)

func (*Engine) SearchLazy

func (e *Engine) SearchLazy(where *Where, pager *Pager, entities interface{}, references ...string)

func (*Engine) SearchOne

func (e *Engine) SearchOne(where *Where, entity Entity, references ...string) (found bool)

func (*Engine) SearchOneLazy

func (e *Engine) SearchOneLazy(where *Where, entity Entity, references ...string) (found bool)

func (*Engine) SearchWithCount

func (e *Engine) SearchWithCount(where *Where, pager *Pager, entities interface{}, references ...string) (totalRows int)

func (*Engine) SearchWithCountLAzy

func (e *Engine) SearchWithCountLAzy(where *Where, pager *Pager, entities interface{}, references ...string) (totalRows int)

func (*Engine) SetLogMetaData

func (e *Engine) SetLogMetaData(key string, value interface{})

type Entity

type Entity interface {
	GetID() uint64

	IsLoaded() bool
	IsInitialised() bool
	Init(engine *Engine)
	IsDirty() bool
	GetDirtyBind() (bind Bind, has bool)
	SetOnDuplicateKeyUpdate(bind Bind)
	SetEntityLogMeta(key string, value interface{})
	SetField(field string, value interface{}) error
	GetFieldLazy(field string) interface{}
	// contains filtered or unexported methods
}

type Enum

type Enum interface {
	GetFields() []string
	GetMapping() map[string]string
	GetDefault() string
	Has(value string) bool
	// contains filtered or unexported methods
}

type EnumModel

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

func (*EnumModel) GetDefault

func (enum *EnumModel) GetDefault() string

func (*EnumModel) GetFields

func (enum *EnumModel) GetFields() []string

func (*EnumModel) GetMapping

func (enum *EnumModel) GetMapping() map[string]string

func (*EnumModel) Has

func (enum *EnumModel) Has(value string) bool

type Event

type Event interface {
	Ack()
	Skip()
	ID() string
	Stream() string
	RawData() map[string]interface{}
	Unserialize(val interface{}) error
	IsSerialized() bool
}

type EventAsMap

type EventAsMap map[string]interface{}

type EventBroker

type EventBroker interface {
	PublishMap(stream string, event EventAsMap) (id string)
	Publish(stream string, event interface{}) (id string)
	Consumer(name, group string) EventsConsumer
	NewFlusher() EventFlusher
}

type EventConsumerHandler

type EventConsumerHandler func([]Event)

type EventFlusher

type EventFlusher interface {
	PublishMap(stream string, event EventAsMap)
	Publish(stream string, event interface{})
	Flush()
}

type EventsConsumer

type EventsConsumer interface {
	Consume(ctx context.Context, count int, blocking bool, handler EventConsumerHandler)
	DisableLoop()
	SetLimit(limit int)
	SetHeartBeat(duration time.Duration, beat func())
	SetErrorHandler(handler ConsumerErrorHandler)
}

type ExecResult

type ExecResult interface {
	LastInsertId() uint64
	RowsAffected() uint64
}

type Flusher

type Flusher interface {
	Track(entity ...Entity) Flusher
	Flush()
	FlushWithCheck() error
	FlushInTransactionWithCheck() error
	FlushWithFullCheck() error
	FlushLazy()
	FlushInTransaction()
	FlushWithLock(lockerPool string, lockName string, ttl time.Duration, waitTimeout time.Duration)
	FlushInTransactionWithLock(lockerPool string, lockName string, ttl time.Duration, waitTimeout time.Duration)
	Clear()
	MarkDirty(entity Entity, queueCode string, ids ...uint64)
	Delete(entity ...Entity) Flusher
	ForceDelete(entity ...Entity) Flusher
}

type ForeignKeyError

type ForeignKeyError struct {
	Message    string
	Constraint string
}

func (*ForeignKeyError) Error

func (err *ForeignKeyError) Error() string

type GetSetProvider

type GetSetProvider func() interface{}

type HealthCheckError

type HealthCheckError struct {
	HealthCheckStep
	Message string
}

type HealthCheckStep

type HealthCheckStep struct {
	Name        string
	Description string
}

type LocalCache

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

func (*LocalCache) Clear

func (c *LocalCache) Clear()

func (*LocalCache) Get

func (c *LocalCache) Get(key string) (value interface{}, ok bool)

func (*LocalCache) GetObjectsCount

func (c *LocalCache) GetObjectsCount() int

func (*LocalCache) GetSet

func (c *LocalCache) GetSet(key string, ttlSeconds int, provider GetSetProvider) interface{}

func (*LocalCache) HMget

func (c *LocalCache) HMget(key string, fields ...string) map[string]interface{}

func (*LocalCache) HMset

func (c *LocalCache) HMset(key string, fields map[string]interface{})

func (*LocalCache) MGet

func (c *LocalCache) MGet(keys ...string) map[string]interface{}

func (*LocalCache) MSet

func (c *LocalCache) MSet(pairs ...interface{})

func (*LocalCache) Remove

func (c *LocalCache) Remove(keys ...string)

func (*LocalCache) Set

func (c *LocalCache) Set(key string, value interface{})

type LocalCacheConfig

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

type Lock

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

func (*Lock) Refresh

func (l *Lock) Refresh(ctx context.Context, ttl time.Duration) bool

func (*Lock) Release

func (l *Lock) Release()

func (*Lock) TTL

func (l *Lock) TTL() time.Duration

type Locker

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

func (*Locker) Obtain

func (l *Locker) Obtain(ctx context.Context, key string, ttl time.Duration, waitTimeout time.Duration) (lock *Lock, obtained bool)

type Log

type Log interface {
	AddFields(fields apexLog.Fielder)
	Debug(message string, fields apexLog.Fielder)
	Info(message string, fields apexLog.Fielder)
	Warn(message string, fields apexLog.Fielder)
	Error(err interface{}, fields apexLog.Fielder)
	ErrorMessage(message string, fields apexLog.Fielder)
	AddFieldsFromHTTPRequest(r *http.Request, ip string)
	SetHTTPResponseCode(code int)
}

type LogQueueValue

type LogQueueValue struct {
	PoolName  string
	TableName string
	ID        uint64
	LogID     uint64
	Meta      map[string]interface{}
	Before    map[string]interface{}
	Changes   map[string]interface{}
	Updated   time.Time
}

type ORM

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

func (*ORM) GetDirtyBind

func (orm *ORM) GetDirtyBind() (bind Bind, has bool)

func (*ORM) GetFieldLazy

func (orm *ORM) GetFieldLazy(field string) interface{}

func (*ORM) GetID

func (orm *ORM) GetID() uint64

func (*ORM) Init

func (orm *ORM) Init(engine *Engine)

func (*ORM) IsDirty

func (orm *ORM) IsDirty() bool

func (*ORM) IsInitialised

func (orm *ORM) IsInitialised() bool

func (*ORM) IsLoaded

func (orm *ORM) IsLoaded() bool

func (*ORM) SetEntityLogMeta

func (orm *ORM) SetEntityLogMeta(key string, value interface{})

func (*ORM) SetField

func (orm *ORM) SetField(field string, value interface{}) error

func (*ORM) SetOnDuplicateKeyUpdate

func (orm *ORM) SetOnDuplicateKeyUpdate(bind Bind)

type Pager

type Pager struct {
	CurrentPage int
	PageSize    int
}

func NewPager

func NewPager(currentPage, pageSize int) *Pager

func (*Pager) GetCurrentPage

func (pager *Pager) GetCurrentPage() int

func (*Pager) GetPageSize

func (pager *Pager) GetPageSize() int

func (*Pager) IncrementPage

func (pager *Pager) IncrementPage()

type PipeLineBool

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

func (*PipeLineBool) Result

func (c *PipeLineBool) Result() (bool, error)

type PipeLineGet

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

func (*PipeLineGet) Result

func (c *PipeLineGet) Result() (value string, has bool, err error)

type PipeLineInt

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

func (*PipeLineInt) Result

func (c *PipeLineInt) Result() (int64, error)

type PipeLineStatus

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

func (*PipeLineStatus) Result

func (c *PipeLineStatus) Result() error

type PipeLineString

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

func (*PipeLineString) Result

func (c *PipeLineString) Result() (string, error)

type PreparedStatement

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

func (*PreparedStatement) Exec

func (p *PreparedStatement) Exec(args ...interface{}) sql.Result

type QueryLoggerSource

type QueryLoggerSource int

type RedisCache

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

func (*RedisCache) Del

func (r *RedisCache) Del(keys ...string)

func (*RedisCache) Eval

func (r *RedisCache) Eval(script string, keys []string, args ...interface{}) interface{}

func (*RedisCache) EvalSha

func (r *RedisCache) EvalSha(sha1 string, keys []string, args ...interface{}) interface{}

func (*RedisCache) Exists

func (r *RedisCache) Exists(keys ...string) int64

func (*RedisCache) Expire

func (r *RedisCache) Expire(key string, expiration time.Duration) bool

func (*RedisCache) FlushDB

func (r *RedisCache) FlushDB()

func (*RedisCache) Get

func (r *RedisCache) Get(key string) (value string, has bool)

func (*RedisCache) GetSet

func (r *RedisCache) GetSet(key string, ttlSeconds int, provider GetSetProvider) interface{}

func (*RedisCache) HDel

func (r *RedisCache) HDel(key string, fields ...string)

func (*RedisCache) HGet

func (r *RedisCache) HGet(key, field string) (value string, has bool)

func (*RedisCache) HGetAll

func (r *RedisCache) HGetAll(key string) map[string]string

func (*RedisCache) HIncrBy

func (r *RedisCache) HIncrBy(key, field string, incr int64) int64

func (*RedisCache) HLen

func (r *RedisCache) HLen(key string) int64

func (*RedisCache) HMget

func (r *RedisCache) HMget(key string, fields ...string) map[string]interface{}

func (*RedisCache) HSet

func (r *RedisCache) HSet(key string, values ...interface{})

func (*RedisCache) Incr

func (r *RedisCache) Incr(key string) int64

func (*RedisCache) IncrBy

func (r *RedisCache) IncrBy(key string, incr int64) int64

func (*RedisCache) Info

func (r *RedisCache) Info(section ...string) string

func (*RedisCache) LLen

func (r *RedisCache) LLen(key string) int64

func (*RedisCache) LPush

func (r *RedisCache) LPush(key string, values ...interface{}) int64

func (*RedisCache) LRange

func (r *RedisCache) LRange(key string, start, stop int64) []string

func (*RedisCache) LRem

func (r *RedisCache) LRem(key string, count int64, value interface{})

func (*RedisCache) LSet

func (r *RedisCache) LSet(key string, index int64, value interface{})

func (*RedisCache) Ltrim

func (r *RedisCache) Ltrim(key string, start, stop int64)

func (*RedisCache) MGet

func (r *RedisCache) MGet(keys ...string) map[string]interface{}

func (*RedisCache) MSet

func (r *RedisCache) MSet(pairs ...interface{})

func (*RedisCache) PipeLine

func (r *RedisCache) PipeLine() *RedisPipeLine

func (*RedisCache) RPop

func (r *RedisCache) RPop(key string) (value string, found bool)

func (*RedisCache) RPush

func (r *RedisCache) RPush(key string, values ...interface{}) int64

func (*RedisCache) RateLimit

func (r *RedisCache) RateLimit(key string, limit redis_rate.Limit) bool

func (*RedisCache) SAdd

func (r *RedisCache) SAdd(key string, members ...interface{}) int64

func (*RedisCache) SCard

func (r *RedisCache) SCard(key string) int64

func (*RedisCache) SPop

func (r *RedisCache) SPop(key string) (string, bool)

func (*RedisCache) SPopN

func (r *RedisCache) SPopN(key string, max int64) []string

func (*RedisCache) ScriptLoad

func (r *RedisCache) ScriptLoad(script string) string

func (*RedisCache) Set

func (r *RedisCache) Set(key string, value interface{}, ttlSeconds int)

func (*RedisCache) Type

func (r *RedisCache) Type(key string) string

func (*RedisCache) XAck

func (r *RedisCache) XAck(stream, group string, ids ...string) int64

func (*RedisCache) XClaim

func (r *RedisCache) XClaim(a *redis.XClaimArgs) []redis.XMessage

func (*RedisCache) XClaimJustID

func (r *RedisCache) XClaimJustID(a *redis.XClaimArgs) []string

func (*RedisCache) XDel

func (r *RedisCache) XDel(stream string, ids ...string) int64

func (*RedisCache) XGroupCreate

func (r *RedisCache) XGroupCreate(stream, group, start string) (key string, exists bool)

func (*RedisCache) XGroupCreateMkStream

func (r *RedisCache) XGroupCreateMkStream(stream, group, start string) (key string, exists bool)

func (*RedisCache) XGroupDelConsumer

func (r *RedisCache) XGroupDelConsumer(stream, group, consumer string) int64

func (*RedisCache) XGroupDestroy

func (r *RedisCache) XGroupDestroy(stream, group string) int64

func (*RedisCache) XInfoGroups

func (r *RedisCache) XInfoGroups(stream string) []redis.XInfoGroup

func (*RedisCache) XInfoStream

func (r *RedisCache) XInfoStream(stream string) *redis.XInfoStream

func (*RedisCache) XLen

func (r *RedisCache) XLen(stream string) int64

func (*RedisCache) XPending

func (r *RedisCache) XPending(stream, group string) *redis.XPending

func (*RedisCache) XPendingExt

func (r *RedisCache) XPendingExt(a *redis.XPendingExtArgs) []redis.XPendingExt

func (*RedisCache) XRange

func (r *RedisCache) XRange(stream, start, stop string, count int64) []redis.XMessage

func (*RedisCache) XRead

func (r *RedisCache) XRead(a *redis.XReadArgs) []redis.XStream

func (*RedisCache) XReadGroup

func (r *RedisCache) XReadGroup(a *redis.XReadGroupArgs) (streams []redis.XStream)

func (*RedisCache) XRevRange

func (r *RedisCache) XRevRange(stream, start, stop string, count int64) []redis.XMessage

func (*RedisCache) XTrim

func (r *RedisCache) XTrim(stream string, maxLen int64, approx bool) (deleted int64)

func (*RedisCache) ZAdd

func (r *RedisCache) ZAdd(key string, members ...*redis.Z) int64

func (*RedisCache) ZCard

func (r *RedisCache) ZCard(key string) int64

func (*RedisCache) ZCount

func (r *RedisCache) ZCount(key string, min, max string) int64

func (*RedisCache) ZRangeWithScores

func (r *RedisCache) ZRangeWithScores(key string, start, stop int64) []redis.Z

func (*RedisCache) ZRevRange

func (r *RedisCache) ZRevRange(key string, start, stop int64) []string

func (*RedisCache) ZRevRangeWithScores

func (r *RedisCache) ZRevRangeWithScores(key string, start, stop int64) []redis.Z

func (*RedisCache) ZScore

func (r *RedisCache) ZScore(key, member string) float64

type RedisCacheConfig

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

type RedisFlusher

type RedisFlusher interface {
	Del(redisPool string, keys ...string)
	PublishMap(stream string, event EventAsMap)
	Publish(stream string, event interface{})
	Flush()
	HSet(redisPool, key string, values ...interface{})
}

type RedisPipeLine

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

func (*RedisPipeLine) Del

func (rp *RedisPipeLine) Del(key ...string) *PipeLineInt

func (*RedisPipeLine) Exec

func (rp *RedisPipeLine) Exec()

func (*RedisPipeLine) Executed

func (rp *RedisPipeLine) Executed() bool

func (*RedisPipeLine) Expire

func (rp *RedisPipeLine) Expire(key string, expiration time.Duration) *PipeLineBool

func (*RedisPipeLine) Get

func (rp *RedisPipeLine) Get(key string) *PipeLineGet

func (*RedisPipeLine) HDel

func (rp *RedisPipeLine) HDel(key string, values ...string) *PipeLineInt

func (*RedisPipeLine) HIncrBy

func (rp *RedisPipeLine) HIncrBy(key, field string, incr int64) *PipeLineInt

func (*RedisPipeLine) HSet

func (rp *RedisPipeLine) HSet(key string, values ...interface{}) *PipeLineInt

func (*RedisPipeLine) Set

func (rp *RedisPipeLine) Set(key string, value interface{}, expiration time.Duration) *PipeLineStatus

func (*RedisPipeLine) XAdd

func (rp *RedisPipeLine) XAdd(stream string, values interface{}) *PipeLineString

type RedisSearch

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

func (*RedisSearch) ForceReindex

func (r *RedisSearch) ForceReindex(index string)

func (*RedisSearch) Info

func (r *RedisSearch) Info(indexName string) *RedisSearchIndexInfo

func (*RedisSearch) ListIndices

func (r *RedisSearch) ListIndices() []string

func (*RedisSearch) Search

func (r *RedisSearch) Search(index string, query *RedisSearchQuery, pager *Pager) (total uint64, rows []*RedisSearchResult)

func (*RedisSearch) SearchKeys

func (r *RedisSearch) SearchKeys(index string, query *RedisSearchQuery, pager *Pager) (total uint64, keys []string)

func (*RedisSearch) SearchRaw

func (r *RedisSearch) SearchRaw(index string, query *RedisSearchQuery, pager *Pager) (total uint64, rows []interface{})

type RedisSearchIndex

type RedisSearchIndex struct {
	Name            string
	RedisPool       string
	Prefixes        []string
	Filter          string
	DefaultLanguage string
	LanguageField   string
	DefaultScore    float64
	ScoreField      string
	PayloadField    string
	MaxTextFields   bool
	Temporary       int
	NoOffsets       bool
	NoNHL           bool
	NoFields        bool
	NoFreqs         bool
	SkipInitialScan bool
	StopWords       []string
	Fields          []RedisSearchIndexField
	Indexer         RedisSearchIndexerFunc
}

func (*RedisSearchIndex) AddGeoField

func (rs *RedisSearchIndex) AddGeoField(name string, sortable, noindex bool)

func (*RedisSearchIndex) AddNumericField

func (rs *RedisSearchIndex) AddNumericField(name string, sortable, noindex bool)

func (*RedisSearchIndex) AddTagField

func (rs *RedisSearchIndex) AddTagField(name string, sortable, noindex bool, separator string)

func (*RedisSearchIndex) AddTextField

func (rs *RedisSearchIndex) AddTextField(name string, weight float64, sortable, noindex, nostem bool)

type RedisSearchIndexAlter

type RedisSearchIndexAlter struct {
	Query     string
	Executing bool
	Documents uint64
	Changes   []string
	Pool      string
	Execute   func()
	// contains filtered or unexported fields
}

type RedisSearchIndexField

type RedisSearchIndexField struct {
	Type         string
	Name         string
	Sortable     bool
	NoIndex      bool
	NoStem       bool
	Weight       float64
	TagSeparator string
}

type RedisSearchIndexInfo

type RedisSearchIndexInfo struct {
	Name                     string
	Options                  RedisSearchIndexInfoOptions
	Definition               RedisSearchIndexInfoDefinition
	Fields                   []RedisSearchIndexInfoField
	NumDocs                  uint64
	MaxDocID                 uint64
	NumTerms                 uint64
	NumRecords               uint64
	InvertedSzMB             float64
	TotalInvertedIndexBlocks float64
	OffsetVectorsSzMB        float64
	DocTableSizeMB           float64
	SortableValuesSizeMB     float64
	KeyTableSizeMB           float64
	RecordsPerDocAvg         int
	BytesPerRecordAvg        int
	OffsetsPerTermAvg        float64
	OffsetBitsPerRecordAvg   float64
	HashIndexingFailures     uint64
	Indexing                 bool
	PercentIndexed           float64
	StopWords                []string
}

type RedisSearchIndexInfoDefinition

type RedisSearchIndexInfoDefinition struct {
	KeyType       string
	Prefixes      []string
	Filter        string
	LanguageField string
	ScoreField    string
	PayloadField  string
	DefaultScore  float64
}

type RedisSearchIndexInfoField

type RedisSearchIndexInfoField struct {
	Name         string
	Type         string
	Weight       float64
	Sortable     bool
	NoStem       bool
	NoIndex      bool
	TagSeparator string
}

type RedisSearchIndexInfoOptions

type RedisSearchIndexInfoOptions struct {
	NoFreqs       bool
	NoOffsets     bool
	NoFields      bool
	MaxTextFields bool
}

type RedisSearchIndexPusher

type RedisSearchIndexPusher interface {
	NewDocument(key string)
	DeleteDocuments(key ...string)
	SetString(key string, value string)
	SetTag(key string, tag ...string)
	SetUint(key string, value uint64)
	SetInt(key string, value int64)
	SetFloat(key string, value float64)
	SetGeo(key string, lon float64, lat float64)
	PushDocument()
	Flush()
	// contains filtered or unexported methods
}

type RedisSearchIndexer

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

func NewRedisSearchIndexer

func NewRedisSearchIndexer(engine *Engine) *RedisSearchIndexer

func (*RedisSearchIndexer) DisableLoop

func (r *RedisSearchIndexer) DisableLoop()

func (*RedisSearchIndexer) Run

func (r *RedisSearchIndexer) Run(ctx context.Context)

func (*RedisSearchIndexer) SetHeartBeat

func (r *RedisSearchIndexer) SetHeartBeat(duration time.Duration, beat func())

type RedisSearchIndexerFunc

type RedisSearchIndexerFunc func(engine *Engine, lastID uint64, pusher RedisSearchIndexPusher) (newID uint64, hasMore bool)

type RedisSearchQuery

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

func (*RedisSearchQuery) ExplainScore

func (q *RedisSearchQuery) ExplainScore() *RedisSearchQuery

func (*RedisSearchQuery) FilterBool

func (q *RedisSearchQuery) FilterBool(field string, value bool) *RedisSearchQuery

func (*RedisSearchQuery) FilterDate

func (q *RedisSearchQuery) FilterDate(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateGreater

func (q *RedisSearchQuery) FilterDateGreater(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateGreaterEqual

func (q *RedisSearchQuery) FilterDateGreaterEqual(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateLess

func (q *RedisSearchQuery) FilterDateLess(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateLessEqual

func (q *RedisSearchQuery) FilterDateLessEqual(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateMinMax

func (q *RedisSearchQuery) FilterDateMinMax(field string, min, max time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateNull

func (q *RedisSearchQuery) FilterDateNull(field string) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateTime

func (q *RedisSearchQuery) FilterDateTime(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateTimeGreater

func (q *RedisSearchQuery) FilterDateTimeGreater(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateTimeGreaterEqual

func (q *RedisSearchQuery) FilterDateTimeGreaterEqual(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateTimeLess

func (q *RedisSearchQuery) FilterDateTimeLess(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateTimeLessEqual

func (q *RedisSearchQuery) FilterDateTimeLessEqual(field string, date time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateTimeMinMax

func (q *RedisSearchQuery) FilterDateTimeMinMax(field string, min, max time.Time) *RedisSearchQuery

func (*RedisSearchQuery) FilterDateTimeNull

func (q *RedisSearchQuery) FilterDateTimeNull(field string) *RedisSearchQuery

func (*RedisSearchQuery) FilterFloat

func (q *RedisSearchQuery) FilterFloat(field string, value float64) *RedisSearchQuery

func (*RedisSearchQuery) FilterFloatGreater

func (q *RedisSearchQuery) FilterFloatGreater(field string, value float64) *RedisSearchQuery

func (*RedisSearchQuery) FilterFloatGreaterEqual

func (q *RedisSearchQuery) FilterFloatGreaterEqual(field string, value float64) *RedisSearchQuery

func (*RedisSearchQuery) FilterFloatLess

func (q *RedisSearchQuery) FilterFloatLess(field string, value float64) *RedisSearchQuery

func (*RedisSearchQuery) FilterFloatLessEqual

func (q *RedisSearchQuery) FilterFloatLessEqual(field string, value float64) *RedisSearchQuery

func (*RedisSearchQuery) FilterFloatMinMax

func (q *RedisSearchQuery) FilterFloatMinMax(field string, min, max float64) *RedisSearchQuery

func (*RedisSearchQuery) FilterFloatNull

func (q *RedisSearchQuery) FilterFloatNull(field string) *RedisSearchQuery

func (*RedisSearchQuery) FilterGeo

func (q *RedisSearchQuery) FilterGeo(field string, lon, lat, radius float64, unit string) *RedisSearchQuery

func (*RedisSearchQuery) FilterInt

func (q *RedisSearchQuery) FilterInt(field string, value int64) *RedisSearchQuery

func (*RedisSearchQuery) FilterIntGreater

func (q *RedisSearchQuery) FilterIntGreater(field string, value int64) *RedisSearchQuery

func (*RedisSearchQuery) FilterIntGreaterEqual

func (q *RedisSearchQuery) FilterIntGreaterEqual(field string, value int64) *RedisSearchQuery

func (*RedisSearchQuery) FilterIntLess

func (q *RedisSearchQuery) FilterIntLess(field string, value int64) *RedisSearchQuery

func (*RedisSearchQuery) FilterIntLessEqual

func (q *RedisSearchQuery) FilterIntLessEqual(field string, value int64) *RedisSearchQuery

func (*RedisSearchQuery) FilterIntMinMax

func (q *RedisSearchQuery) FilterIntMinMax(field string, min, max int64) *RedisSearchQuery

func (*RedisSearchQuery) FilterIntNull

func (q *RedisSearchQuery) FilterIntNull(field string) *RedisSearchQuery

func (*RedisSearchQuery) FilterString

func (q *RedisSearchQuery) FilterString(field string, value ...string) *RedisSearchQuery

func (*RedisSearchQuery) FilterTag

func (q *RedisSearchQuery) FilterTag(field string, tag ...string) *RedisSearchQuery

func (*RedisSearchQuery) Highlight

func (q *RedisSearchQuery) Highlight(field ...string) *RedisSearchQuery

func (*RedisSearchQuery) HighlightTags

func (q *RedisSearchQuery) HighlightTags(openTag, closeTag string) *RedisSearchQuery

func (*RedisSearchQuery) InFields

func (q *RedisSearchQuery) InFields(field ...string) *RedisSearchQuery

func (*RedisSearchQuery) InKeys

func (q *RedisSearchQuery) InKeys(key ...string) *RedisSearchQuery

func (*RedisSearchQuery) InOrder

func (q *RedisSearchQuery) InOrder() *RedisSearchQuery

func (*RedisSearchQuery) Lang

func (q *RedisSearchQuery) Lang(lang string) *RedisSearchQuery

func (*RedisSearchQuery) NoStopWords

func (q *RedisSearchQuery) NoStopWords() *RedisSearchQuery

func (*RedisSearchQuery) Query

func (q *RedisSearchQuery) Query(query string) *RedisSearchQuery

func (*RedisSearchQuery) QueryRaw

func (q *RedisSearchQuery) QueryRaw(query string) *RedisSearchQuery

func (*RedisSearchQuery) Return

func (q *RedisSearchQuery) Return(field ...string) *RedisSearchQuery

func (*RedisSearchQuery) Slop

func (q *RedisSearchQuery) Slop(slop int) *RedisSearchQuery

func (*RedisSearchQuery) Sort

func (q *RedisSearchQuery) Sort(field string, desc bool) *RedisSearchQuery

func (*RedisSearchQuery) Summarize

func (q *RedisSearchQuery) Summarize(field ...string) *RedisSearchQuery

func (*RedisSearchQuery) SummarizeOptions

func (q *RedisSearchQuery) SummarizeOptions(separator string, frags, len int) *RedisSearchQuery

func (*RedisSearchQuery) Verbatim

func (q *RedisSearchQuery) Verbatim() *RedisSearchQuery

func (*RedisSearchQuery) WithPayLoads

func (q *RedisSearchQuery) WithPayLoads() *RedisSearchQuery

func (*RedisSearchQuery) WithScores

func (q *RedisSearchQuery) WithScores() *RedisSearchQuery

type RedisSearchResult

type RedisSearchResult struct {
	Key          string
	Fields       []interface{}
	Score        float64
	ExplainScore []interface{}
	PayLoad      string
}

func (*RedisSearchResult) Value

func (r *RedisSearchResult) Value(field string) interface{}

type Registry

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

func InitByYaml

func InitByYaml(yaml map[string]interface{}) (registry *Registry)

func (*Registry) RegisterClickHouse

func (r *Registry) RegisterClickHouse(url string, code ...string)

func (*Registry) RegisterElastic

func (r *Registry) RegisterElastic(url string, code ...string)

func (*Registry) RegisterElasticIndex

func (r *Registry) RegisterElasticIndex(index ElasticIndexDefinition, serverPool ...string)

func (*Registry) RegisterElasticWithTraceLog

func (r *Registry) RegisterElasticWithTraceLog(url string, code ...string)

func (*Registry) RegisterEntity

func (r *Registry) RegisterEntity(entity ...Entity)

func (*Registry) RegisterEnumMap

func (r *Registry) RegisterEnumMap(code string, val map[string]string, defaultValue string)

func (*Registry) RegisterEnumSlice

func (r *Registry) RegisterEnumSlice(code string, val []string)

func (*Registry) RegisterEnumStruct

func (r *Registry) RegisterEnumStruct(code string, val Enum)

func (*Registry) RegisterLocalCache

func (r *Registry) RegisterLocalCache(size int, code ...string)

func (*Registry) RegisterLocker

func (r *Registry) RegisterLocker(code string, redisCode string)

func (*Registry) RegisterMySQLPool

func (r *Registry) RegisterMySQLPool(dataSourceName string, code ...string)

func (*Registry) RegisterRedis

func (r *Registry) RegisterRedis(address string, db int, code ...string)

func (*Registry) RegisterRedisSearchIndex

func (r *Registry) RegisterRedisSearchIndex(index ...*RedisSearchIndex)

func (*Registry) RegisterRedisSentinel

func (r *Registry) RegisterRedisSentinel(masterName string, db int, sentinels []string, code ...string)

func (*Registry) RegisterRedisStream

func (r *Registry) RegisterRedisStream(name string, redisPool string, groups []string)

func (*Registry) SetDefaultEncoding

func (r *Registry) SetDefaultEncoding(encoding string)

func (*Registry) Validate

func (r *Registry) Validate() (ValidatedRegistry, error)

type Rows

type Rows interface {
	Next() bool
	Scan(dest ...interface{})
	Columns() []string
}

type SQLRow

type SQLRow interface {
	Scan(dest ...interface{}) error
}

type SQLRows

type SQLRows interface {
	Next() bool
	Err() error
	Close() error
	Scan(dest ...interface{}) error
	Columns() ([]string, error)
}

type SearchOptions

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

func (*SearchOptions) AddAggregation

func (p *SearchOptions) AddAggregation(name string, aggregation elastic.Aggregation) *SearchOptions

func (*SearchOptions) AddSort

func (p *SearchOptions) AddSort(field string, ascending bool) *SearchOptions

type TableSchema

type TableSchema interface {
	GetTableName() string
	GetType() reflect.Type
	DropTable(engine *Engine)
	TruncateTable(engine *Engine)
	UpdateSchema(engine *Engine)
	UpdateSchemaAndTruncateTable(engine *Engine)
	GetMysql(engine *Engine) *DB
	GetLocalCache(engine *Engine) (cache *LocalCache, has bool)
	GetRedisCache(engine *Engine) (cache *RedisCache, has bool)
	GetReferences() []string
	GetColumns() []string
	GetUsage(registry ValidatedRegistry) map[reflect.Type][]string
	GetSchemaChanges(engine *Engine) (has bool, alters []Alter)
}

type ValidatedRegistry

type ValidatedRegistry interface {
	CreateEngine() *Engine
	GetTableSchema(entityName string) TableSchema
	GetTableSchemaForEntity(entity Entity) TableSchema
	GetSourceRegistry() *Registry
	GetEnum(code string) Enum
	GetEnums() map[string]Enum
	GetRedisStreams() map[string]map[string][]string
	GetRedisPools(groupByAddress bool, db ...int) []string
	GetRedisSearchIndices() map[string][]*RedisSearchIndex
	GetEntities() map[string]reflect.Type
}

type Where

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

func NewWhere

func NewWhere(query string, parameters ...interface{}) *Where

func (*Where) Append

func (where *Where) Append(query string, parameters ...interface{})

func (*Where) GetParameters

func (where *Where) GetParameters() []interface{}

func (*Where) String

func (where *Where) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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